| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026 |
- <!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
- <title>二级列表</title>
- <script src="/js/mp_base/base.js"></script>
- <style>
- #app {
- background: #f5f5f5;
- min-height: 100vh;
- }
- [v-cloak] {
- display: none !important;
- }
- .search-filter-container {
- background: #f5f5f5;
- padding: 15px;
- position: sticky;
- top: 0;
- z-index: 100;
- display: flex;
- flex-wrap: wrap;
- gap: 10px;
- align-items: center;
- /* 搜索条件右对齐,和 mp_objList 保持一致 by xu 2026-03-06 */
- justify-content: flex-end;
- }
- .search-filter-container .ss-select-container,
- .search-filter-container .input,
- .search-filter-container .ss-search-date-picker {
- border-radius: 6px;
- overflow: hidden;
- }
- .loading-container,
- .error-container {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- min-height: 220px;
- color: #666;
- padding: 24px;
- text-align: center;
- }
- .loading-spinner {
- width: 40px;
- height: 40px;
- border: 4px solid #f3f3f3;
- border-top: 4px solid #40ac6d;
- border-radius: 50%;
- animation: spin 1s linear infinite;
- margin-bottom: 15px;
- }
- @keyframes spin {
- 0% { transform: rotate(0deg); }
- 100% { transform: rotate(360deg); }
- }
- .error-text {
- color: #d03050;
- line-height: 1.7;
- }
- .list-container {
- padding: 0 15px 8px;
- }
- .empty-state {
- text-align: center;
- padding: 60px 20px;
- color: #999;
- }
- .empty-icon {
- font-size: 48px;
- margin-bottom: 15px;
- }
- .empty-text {
- font-size: 16px;
- }
- .card-content .card-header {
- display: flex;
- align-items: center;
- gap: 8px;
- margin-bottom: 10px;
- }
- .card-content .card-title {
- font-size: 16px;
- font-weight: bold;
- color: #333;
- line-height: 1.5;
- word-break: break-all;
- }
- .draft-tag {
- flex: 0 0 auto;
- padding: 2px 8px;
- border-radius: 999px;
- background: rgba(64, 172, 109, 0.12);
- color: #2a8f58;
- font-size: 12px;
- }
- .card-content .card-description {
- font-size: 14px;
- color: #666;
- margin-bottom: 8px;
- line-height: 1.6;
- word-break: break-all;
- }
- .card-content .attribute-group {
- display: flex;
- flex-wrap: wrap;
- column-gap: 10px;
- }
- .card-content .attribute-item {
- display: flex;
- margin-bottom: 5px;
- max-width: 100%;
- }
- .card-content .attr-label {
- font-size: 13px;
- color: #999;
- flex: 0 0 auto;
- }
- .card-content .attr-value {
- font-size: 13px;
- color: #333;
- word-break: break-all;
- }
- .load-more-container {
- text-align: center;
- padding: 20px;
- color: #999;
- font-size: 14px;
- }
- .load-more-loading {
- color: #007aff;
- }
- .load-more-end {
- color: #999;
- }
- .load-more-tip {
- color: #ccc;
- }
- .back-to-top-btn {
- width: 50px;
- height: 50px;
- border-radius: 50%;
- background: rgba(87, 93, 109, 0.5);
- display: flex;
- justify-content: center;
- align-items: center;
- position: fixed;
- bottom: 200px;
- right: 15px;
- cursor: pointer;
- transition: all 0.3s ease;
- z-index: 999;
- }
- .back-to-top-btn:active {
- transform: scale(0.9);
- }
- .back-to-top-inner {
- width: 42px;
- height: 42px;
- border-radius: 50%;
- background: rgba(87, 93, 109, 0.5);
- display: flex;
- justify-content: center;
- align-items: center;
- }
- .search-modal-mask {
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background: rgba(0, 0, 0, 0.5);
- z-index: 1000;
- display: flex;
- align-items: flex-end;
- }
- .search-modal-content {
- width: 100%;
- background: white;
- animation: slideUp 0.3s ease-out;
- position: relative;
- }
- @keyframes slideUp {
- from { transform: translateY(100%); }
- to { transform: translateY(0); }
- }
- .search-input-container {
- display: flex;
- align-items: center;
- height: 50px;
- background: white;
- border-top: 1px solid #e5e5e5;
- }
- .search-input {
- flex: 1;
- height: 100%;
- border: none;
- outline: none;
- padding: 0 15px;
- font-size: 16px;
- background: transparent;
- }
- .search-divider {
- width: 1px;
- height: 24px;
- background: #e5e5e5;
- }
- .search-icon-btn {
- width: 56px;
- height: 100%;
- border: none;
- background: white;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- .search-icon-btn:active {
- background: #f5f5f5;
- }
- </style>
- </head>
- <body>
- <div id="app" v-cloak>
- <!-- 二级列表筛选条:兼容 PC 的搜索字段、范围按钮和根功能按钮 by xu 2026-03-06 -->
- <div class="search-filter-container">
- <template v-for="field in searchFieldList" :key="field.name">
- <ss-select
- v-if="field.cbName"
- v-model="selectedFilters[field.name]"
- :placeholder="field.desc || '请选择'"
- :options="filterSelectOptions[field.name] || []"
- @change="handleFilterChange"
- ></ss-select>
- <ss-search-date-picker
- v-else-if="isDateField(field)"
- v-model="selectedFilters[field.name]"
- :name="field.name"
- :placeholder="field.desc || ''"
- width="140px"
- @change="applyFilters"
- ></ss-search-date-picker>
- <ss-search-input
- v-else
- v-model="selectedFilters[field.name]"
- :name="field.name"
- :placeholder="field.desc || ''"
- width="120px"
- @search="applyFilters"
- ></ss-search-input>
- </template>
- <ss-search-button
- :text="getCurrentScopeText()"
- :options="scopeButtonOptions"
- ></ss-search-button>
- <ss-search-button
- v-if="hasKeyWord"
- text="关键词"
- @click="openSearchModal"
- ></ss-search-button>
- <ss-search-button
- v-for="(button, index) in rootFuncList"
- :key="`${getButtonText(button)}-${index}`"
- :text="getButtonText(button)"
- @click="handleRootButtonClick(button)"
- ></ss-search-button>
- </div>
- <div v-if="loading" class="loading-container">
- <div class="loading-spinner"></div>
- <div class="loading-text">加载中...</div>
- </div>
- <div v-else-if="errorMessage" class="error-container">
- <div class="error-text">{{ errorMessage }}</div>
- </div>
- <div v-else class="list-container">
- <div v-if="list.length === 0" class="empty-state">
- <div class="empty-icon">📋</div>
- <div class="empty-text">暂无数据</div>
- </div>
- <div v-else>
- <!-- 二级列表卡片:兼容 draftList/objList 与 catList/title 结构 by xu 2026-03-06 -->
- <ss-card
- v-for="(item, index) in list"
- :key="`${index}-${item.ssObjId || item.id || item.firstDisplay || ''}`"
- :item="item"
- @click="handleCardClick(item)"
- @button-click="handleCardAction"
- >
- <div class="card-content">
- <div class="card-header" v-if="item.firstDisplay || item.isDraft">
- <span v-if="item.isDraft" class="draft-tag">草稿</span>
- <div class="card-title">{{ item.firstDisplay || '未命名记录' }}</div>
- </div>
- <div class="card-description" v-if="item.secondDisplay">
- {{ item.secondDisplay }}
- </div>
- <div class="card-attributes" v-if="item.thirdDisplay && item.thirdDisplay.length > 0">
- <div
- v-for="(group, groupIndex) in item.thirdDisplay"
- :key="groupIndex"
- class="attribute-group"
- >
- <div
- v-for="(attr, attrIndex) in group"
- :key="attrIndex"
- class="attribute-item"
- >
- <span class="attr-label">{{ getAttrLabel(attr) }}:</span>
- <span class="attr-value">{{ attr.displayValue }}</span>
- </div>
- </div>
- </div>
- </div>
- </ss-card>
- </div>
- </div>
- <div class="load-more-container" v-if="list.length > 0">
- <div v-if="isLoadingMore" class="load-more-loading">
- <span>正在加载更多...</span>
- </div>
- <div v-else-if="!hasMore" class="load-more-end">
- <span>没有更多数据了</span>
- </div>
- <div v-else class="load-more-tip">
- <span>滚动到底部加载更多</span>
- </div>
- </div>
- <div
- v-if="showBackToTop"
- class="back-to-top-btn"
- @touchstart="handleLongPressStart"
- @touchend="handleLongPressEnd"
- @touchcancel="handleLongPressCancel"
- @click.prevent="handleBackToTopClick"
- >
- <div class="back-to-top-inner">
- <Icon name="icon-huidaodingbu" size="40" color="#fff"></Icon>
- </div>
- </div>
- <div v-if="showSearchModal" class="search-modal-mask" @click="closeSearchModal">
- <div class="search-modal-content" @click.stop>
- <div class="search-input-container">
- <input
- ref="searchInput"
- v-model="searchKeyword"
- type="search"
- inputmode="search"
- class="search-input"
- placeholder="请输入关键词"
- @keyup.enter="performSearch"
- autocomplete="off"
- />
- <div class="search-divider"></div>
- <button class="search-icon-btn" @click="performSearch">
- <Icon name="icon-chazhao" size="24" color="#575d6d"></Icon>
- </button>
- </div>
- </div>
- </div>
- </div>
- <script>
- window.SS.ready(function () {
- window.SS.dom.initializeFormApp({
- el: '#app',
- data() {
- return {
- loading: true,
- errorMessage: '',
- list: [],
- currentPage: 1,
- pageSize: 12,
- hasMore: true,
- isLoadingMore: false,
- pageParams: {},
- service: '',
- ssSearchCobjServName: '',
- requestParentViewObject: '',
- ssObjName: '',
- ssObjId: '',
- ssPobjIdName: '',
- management: '1',
- searchFieldList: [],
- rootFuncList: [],
- selectedFilters: {},
- filterSelectOptions: {},
- dictCache: new Map(),
- ssPaging: null,
- hasKeyWord: false,
- scopeButtonOptions: [],
- showBackToTop: false,
- showSearchModal: false,
- searchKeyword: '',
- longPressTimer: null,
- isLongPress: false,
- requestSeq: 0,
- };
- },
- mounted() {
- this.setupScopeButtons();
- this.initPage();
- this.setupRefreshListener();
- this.setupScrollListener();
- },
- beforeUnmount() {
- if (this.refreshCleanup) {
- this.refreshCleanup();
- }
- if (this.scrollCleanup) {
- this.scrollCleanup();
- }
- },
- methods: {
- // 二级列表初始化:同时兼容直接传 cobj 服务和先走 init 再拿 ssSearchCobjServName 的两种入口 by xu 2026-03-06
- async initPage() {
- try {
- this.pageParams = this.getUrlParams();
- this.service = String(this.pageParams.service || '').trim();
- this.ssSearchCobjServName = String(this.pageParams.ssSearchCobjServName || '').trim();
- this.requestParentViewObject = String(this.pageParams.requestParentViewObject || '').trim();
- this.ssObjName = String(this.pageParams.ssObjName || this.pageParams.ssobjname || '').trim();
- this.ssObjId = String(this.pageParams.ssObjId || this.pageParams.ssobjid || '').trim();
- this.ssPobjIdName = String(this.pageParams.ssPobjIdName || '').trim();
- this.management = String(this.pageParams.management || '1');
- this.searchKeyword = String(this.pageParams.ssKeyword || '').trim();
- this.setupScopeButtons();
- if (this.searchKeyword) {
- this.selectedFilters = {
- ...this.selectedFilters,
- ssKeyword: this.searchKeyword,
- };
- }
- if (this.ssSearchCobjServName) {
- await this.loadData(1, false);
- return;
- }
- if (!this.service) {
- this.errorMessage = '缺少服务名,无法加载二级列表';
- return;
- }
- await this.resolveInitService();
- } catch (error) {
- console.error('❌ 二级列表初始化失败:', error);
- this.errorMessage = '页面初始化失败,请稍后重试';
- } finally {
- this.loading = false;
- }
- },
- async resolveInitService() {
- const reqId = ++this.requestSeq;
- this.loading = true;
- this.errorMessage = '';
- try {
- const requestParams = this.buildRequestParams(1);
- const result = await request.post(
- `/service?ssServ=${this.service}&management=${encodeURIComponent(this.management)}&isReady=1`,
- requestParams,
- {
- loading: false,
- formData: true,
- }
- );
- if (reqId !== this.requestSeq) return;
- const rawData = result && result.data ? result.data : {};
- if (this.isBizError(rawData)) {
- this.errorMessage = this.formatBizError(rawData);
- return;
- }
- const payload = this.unwrapResponseData(rawData);
- const resolvedCobjService = String(payload.ssSearchCobjServName || '').trim();
- if (resolvedCobjService) {
- this.ssSearchCobjServName = resolvedCobjService;
- if (!this.requestParentViewObject) {
- this.requestParentViewObject = String(payload.requestParentViewObject || '').trim();
- }
- if (!this.ssPobjIdName) {
- this.ssPobjIdName = String(payload.ssPobjIdName || '').trim();
- }
- if (!this.ssObjName) {
- this.ssObjName = String(payload.ssObjName || payload.objName || '').trim();
- }
- if (!this.ssObjId) {
- this.ssObjId = String(payload.ssObjId || payload.objId || '').trim();
- }
- await this.loadData(1, false);
- return;
- }
- await this.applyApiData(payload, false);
- } catch (error) {
- console.error('❌ 初始化服务请求失败:', error);
- this.errorMessage = '初始化失败,请稍后重试';
- }
- },
- async loadData(pageNo = 1, isLoadMore = false) {
- const serviceName = String(this.ssSearchCobjServName || this.service || '').trim();
- if (!serviceName) {
- this.errorMessage = '缺少二级列表服务名';
- return;
- }
- if (isLoadMore && this.isLoadingMore) return;
- if (!isLoadMore && this.loading && this.list.length > 0) return;
- const reqId = ++this.requestSeq;
- this.errorMessage = '';
- if (isLoadMore) {
- this.isLoadingMore = true;
- } else {
- this.loading = true;
- }
- try {
- const requestParams = this.buildRequestParams(pageNo);
- const result = await request.post(
- `/service?ssServ=${serviceName}&management=${encodeURIComponent(this.management)}&isReady=1`,
- requestParams,
- {
- loading: false,
- formData: true,
- }
- );
- if (reqId !== this.requestSeq) return;
- const rawData = result && result.data ? result.data : {};
- if (this.isBizError(rawData)) {
- this.errorMessage = this.formatBizError(rawData);
- return;
- }
- const payload = this.unwrapResponseData(rawData);
- await this.applyApiData(payload, isLoadMore);
- } catch (error) {
- console.error('❌ 二级列表加载失败:', error);
- this.errorMessage = '加载失败,请稍后重试';
- } finally {
- if (reqId === this.requestSeq) {
- this.loading = false;
- this.isLoadingMore = false;
- }
- }
- },
- async applyApiData(payload, isLoadMore = false) {
- const data = payload && typeof payload === 'object' ? payload : {};
- if (Array.isArray(data.searchFieldList)) {
- this.searchFieldList = data.searchFieldList;
- }
- if (Array.isArray(data.rootFuncList) || Array.isArray(data.buttonList)) {
- this.rootFuncList = data.rootFuncList || data.buttonList || [];
- }
- if (Object.prototype.hasOwnProperty.call(data, 'hasKeyWord') || Object.prototype.hasOwnProperty.call(data, 'hasKeyword')) {
- this.hasKeyWord = !!(data.hasKeyWord || data.hasKeyword);
- }
- if (data.ssPaging && typeof data.ssPaging === 'object') {
- this.ssPaging = {
- pageNo: Number(data.ssPaging.pageNo || 1),
- rowNumPer: Number(data.ssPaging.rowNumPer || this.pageSize || 12),
- rowNum: Number(data.ssPaging.rowNum || 0),
- };
- if (this.ssPaging.rowNumPer > 0) {
- this.pageSize = this.ssPaging.rowNumPer;
- }
- }
- this.ensureSelectedFilters();
- await this.generateFilterOptions();
- const draftList = Array.isArray(data.draftList)
- ? data.draftList.map(item => ({ ...item, __isDraft: true }))
- : [];
- const objList = Array.isArray(data.objList)
- ? data.objList.map(item => ({ ...item, __isDraft: false }))
- : Array.isArray(data.objectList)
- ? data.objectList.map(item => ({ ...item, __isDraft: false }))
- : [];
- const formattedList = await this.formatCobjItems(draftList.concat(objList));
- if (isLoadMore) {
- this.list = this.list.concat(formattedList);
- this.currentPage = Number(this.currentPage || 1) + 1;
- } else {
- this.list = formattedList;
- this.currentPage = Number(this.ssPaging && this.ssPaging.pageNo ? this.ssPaging.pageNo : 1);
- }
- if (this.ssPaging && this.ssPaging.rowNum) {
- this.hasMore = this.list.length < Number(this.ssPaging.rowNum || 0);
- } else {
- this.hasMore = formattedList.length >= this.pageSize;
- }
- this.errorMessage = '';
- },
- async formatCobjItems(rawList) {
- const list = Array.isArray(rawList) ? rawList : [];
- const formattedList = await window.formatObjectList(list, this.dictCache);
- return formattedList.map((item, index) => {
- const rawItem = list[index] || {};
- const nextItem = {
- ...item,
- isDraft: !!rawItem.__isDraft,
- buttons: [],
- };
- if (Array.isArray(rawItem.catList) && rawItem.catList.length) {
- nextItem.thirdDisplay = [
- rawItem.catList
- .map(catItem => {
- if (!catItem || typeof catItem !== 'object') return null;
- const rawValue = catItem.val;
- let displayValue = rawValue === undefined || rawValue === null ? '' : String(rawValue);
- if (catItem.fmt && window.H5FieldFormatter && typeof window.H5FieldFormatter.formatDate === 'function') {
- displayValue = window.H5FieldFormatter.formatDate(rawValue, catItem.fmt) || displayValue;
- }
- return {
- field: {
- desc: String(catItem.desc || ''),
- },
- value: rawValue,
- displayValue,
- };
- })
- .filter(Boolean),
- ].filter(group => group.length > 0);
- }
- if (rawItem.chg) {
- nextItem.buttons = [{
- title: '变动',
- onclick: () => this.handleServiceAction(rawItem.chg),
- }];
- }
- return nextItem;
- });
- },
- unwrapResponseData(data) {
- if (!data || typeof data !== 'object') return {};
- return data.ssData && typeof data.ssData === 'object' ? data.ssData : data;
- },
- isBizError(data) {
- return !!(data && typeof data === 'object' && Object.prototype.hasOwnProperty.call(data, 'ssCode') && Object.prototype.hasOwnProperty.call(data, 'ssMsg') && !data.ssData);
- },
- formatBizError(data) {
- return `错误(${data.ssCode}):${data.ssMsg == null ? '' : data.ssMsg}`;
- },
- getUrlParams() {
- return NavigationManager.getUrlParam();
- },
- buildRequestParams(pageNo = 1) {
- const params = {
- pageNo,
- rowNumPer: this.pageSize,
- management: this.management,
- isReady: '1',
- ...this.getActiveFilterParams(this.selectedFilters),
- };
- if (this.ssObjId) {
- const objIdKey = String(this.ssPobjIdName || '').trim() || (this.ssObjName ? `${this.ssObjName}id` : 'ssObjId');
- params[objIdKey] = this.ssObjId;
- }
- if (this.requestParentViewObject) {
- params.requestParentViewObject = this.requestParentViewObject;
- }
- return params;
- },
- getActiveFilterParams(source) {
- const params = {};
- const data = source && typeof source === 'object' ? source : {};
- Object.entries(data).forEach(([key, value]) => {
- if (value === '' || value === null || value === undefined) return;
- params[key] = value;
- });
- return params;
- },
- ensureSelectedFilters() {
- const nextFilters = { ...this.selectedFilters };
- (this.searchFieldList || []).forEach(field => {
- if (!field || !field.name) return;
- if (nextFilters[field.name] !== undefined) return;
- const pageValue = this.pageParams[field.name];
- nextFilters[field.name] = pageValue !== undefined ? String(pageValue) : '';
- });
- if (this.hasKeyWord) {
- if (nextFilters.ssKeyword === undefined) {
- nextFilters.ssKeyword = this.searchKeyword || '';
- }
- this.searchKeyword = String(nextFilters.ssKeyword || '');
- }
- this.selectedFilters = nextFilters;
- },
- async generateFilterOptions() {
- for (const field of this.searchFieldList || []) {
- if (!field || !field.name || !field.cbName) continue;
- if (Array.isArray(this.filterSelectOptions[field.name]) && this.filterSelectOptions[field.name].length > 0) continue;
- try {
- const options = await window.getDictOptions(field.cbName, this.dictCache);
- this.filterSelectOptions = {
- ...this.filterSelectOptions,
- [field.name]: [{ n: `全部${field.desc || ''}`, v: '' }].concat(options || []),
- };
- } catch (error) {
- console.error('❌ 获取筛选选项失败:', field.cbName, error);
- }
- }
- },
- isDateField(field) {
- const type = Number(field && field.type);
- return type === 3 || type === 11;
- },
- getFieldDesc(fieldName) {
- const field = (this.searchFieldList || []).find(item => item && item.name === fieldName);
- return field ? field.desc : fieldName;
- },
- getAttrLabel(attr) {
- if (!attr || typeof attr !== 'object') return '';
- return attr.field && attr.field.desc ? attr.field.desc : '';
- },
- getButtonText(button) {
- if (!button || typeof button !== 'object') return '';
- return button.desc || button.title || button.buttonName || button.name || button.function?.desc || '';
- },
- setupScopeButtons() {
- const scopeList = [
- { id: '99', text: '所有' },
- { id: '2', text: '管理' },
- { id: '1', text: '创建' },
- { id: '3', text: '已办' },
- { id: '55', text: '停用' },
- ];
- this.scopeButtonOptions = scopeList.map(item => ({
- text: item.text,
- onclick: () => this.switchScope(item.id),
- }));
- },
- getCurrentScopeText() {
- const scopeMap = {
- '99': '所有',
- '2': '管理',
- '1': '创建',
- '3': '已办',
- '55': '停用',
- };
- return scopeMap[String(this.management || '1')] || '所有';
- },
- async switchScope(scopeId) {
- this.management = String(scopeId || '1');
- await this.applyFilters();
- },
- handleFilterChange() {
- this.applyFilters();
- },
- async applyFilters() {
- this.currentPage = 1;
- this.hasMore = true;
- this.list = [];
- await this.loadData(1, false);
- },
- handleRootButtonClick(button) {
- if (!NavigationManager.goToFromButton(button)) {
- this.handleServiceAction(button.function || button);
- }
- },
- handleServiceAction(serviceAction) {
- if (!serviceAction || typeof serviceAction !== 'object') {
- this.showToast('当前操作缺少配置', 'warning');
- return;
- }
- const navButton = {
- dest: serviceAction.dest || serviceAction.ssDest || '',
- servName: serviceAction.servName || serviceAction.ssServ || serviceAction.service || '',
- service: serviceAction.servName || serviceAction.ssServ || serviceAction.service || '',
- title: serviceAction.desc || serviceAction.title || '',
- desc: serviceAction.desc || serviceAction.title || '',
- };
- if (NavigationManager.goToFromButton(navButton)) {
- return;
- }
- this.showToast('暂不支持当前操作跳转', 'warning');
- },
- handleCardClick(item) {
- const play = (item && (item.play || (item.service && item.service.play))) || null;
- if (!play) {
- this.showToast('当前记录缺少查看配置', 'warning');
- return;
- }
- const serviceName = String(play.servName || play.ssServ || '').trim();
- const destName = String(play.dest || 'objPlay').trim();
- const paramName = String(play.param_name || '').trim();
- const paramValue = play.param_value;
- const ssToken = String(play.ssToken || '').trim();
- const paramText = typeof play.parm === 'string' ? play.parm : '';
- if (!serviceName) {
- this.showToast('缺少查看服务名', 'warning');
- return;
- }
- NavigationManager.goTo('mp_objplay', {
- title: play.desc || play.title || '查看',
- service: serviceName,
- dest: destName,
- ssDest: destName,
- param: paramText,
- playParamName: paramName,
- playParamValue: paramValue,
- ssToken,
- ssObjId: item.ssObjId || this.ssObjId || '',
- ssObjName: item.ssObjName || this.ssObjName || '',
- });
- },
- handleCardAction() {
- },
- async loadMore() {
- if (!this.hasMore || this.isLoadingMore) return;
- await this.loadData(Number(this.currentPage || 1) + 1, true);
- },
- setupRefreshListener() {
- this.refreshCleanup = NavigationManager.onRefreshNotify(() => {
- this.applyFilters();
- });
- },
- setupScrollListener() {
- let timer = null;
- const handleScroll = () => {
- clearTimeout(timer);
- timer = setTimeout(() => {
- const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
- const windowHeight = window.innerHeight;
- const documentHeight = document.documentElement.scrollHeight;
- this.showBackToTop = scrollTop > 300;
- if (scrollTop + windowHeight >= documentHeight - 50) {
- this.loadMore();
- }
- }, 200);
- };
- window.addEventListener('scroll', handleScroll);
- this.scrollCleanup = () => {
- window.removeEventListener('scroll', handleScroll);
- };
- },
- scrollToTop() {
- window.scrollTo({ top: 0, behavior: 'smooth' });
- },
- handleBackToTopClick() {
- if (!this.isLongPress) {
- this.scrollToTop();
- }
- this.isLongPress = false;
- },
- handleLongPressStart() {
- if (!this.hasKeyWord) return;
- this.isLongPress = false;
- this.longPressTimer = setTimeout(() => {
- this.isLongPress = true;
- this.openSearchModal();
- if (navigator.vibrate) {
- navigator.vibrate(50);
- }
- }, 500);
- },
- handleLongPressEnd() {
- if (this.longPressTimer) {
- clearTimeout(this.longPressTimer);
- this.longPressTimer = null;
- }
- },
- handleLongPressCancel() {
- if (this.longPressTimer) {
- clearTimeout(this.longPressTimer);
- this.longPressTimer = null;
- }
- this.isLongPress = false;
- },
- openSearchModal() {
- this.showSearchModal = true;
- this.$nextTick(() => {
- setTimeout(() => {
- if (this.$refs.searchInput) {
- this.$refs.searchInput.click();
- this.$refs.searchInput.focus();
- }
- }, 100);
- });
- },
- closeSearchModal() {
- this.showSearchModal = false;
- },
- async performSearch() {
- const keyword = String(this.searchKeyword || '').trim();
- this.selectedFilters = {
- ...this.selectedFilters,
- ssKeyword: keyword,
- };
- this.closeSearchModal();
- await this.applyFilters();
- },
- showToast(message, type = 'info') {
- console.log(`${type.toUpperCase()}: ${message}`);
- alert(message);
- },
- },
- });
- });
- </script>
- </body>
- </html>
|