From c1d2051abc8ca88cd07f0d7c56c0dbf8165d5c33 Mon Sep 17 00:00:00 2001 From: riku <risaku@163.com> Date: 星期四, 18 九月 2025 17:02:22 +0800 Subject: [PATCH] 2025.9.18 数据产品(待完成) --- src/views/fysp/config/device/CompDeviceMatchEdit.vue | 2 src/views/fysp/config/components/CompInfoSearchFysp.vue | 72 +++ src/views/fysp/data-product/base-data-product/ProdInspectionInfo.vue | 104 +++++ src/components.d.ts | 7 src/components/SideList.vue | 276 +++++++------ src/components/ToolBar.vue | 2 src/views/HomePage.vue | 43 + src/views/fysp/support/JingAnSupport.vue | 46 ++ src/views/fysp/data-product/base-data-product/ProdEvaluationInfo.vue | 98 ++++ src/components/core/BaseContentLayout.vue | 20 src/components/search-option/FYSearchBar.vue | 2 src/router/index.js | 12 src/views/fysp/data-product/base-data-product/components/ProdDownload.vue | 70 +++ src/views/fysp/data-product/base-data-product/components/BaseProdProcess.vue | 60 ++ src/components/table/FYTable.vue | 44 +- src/api/fysp/nightConstructionApi.js | 13 src/views/fysp/check/ProCheck.vue | 16 src/views/fysp/config/components/CompInfoSearch.vue | 37 + src/components/SearchBar.vue | 7 src/views/fysp/data-product/base-data-product/ProdManage.vue | 19 src/views/fysp/data-product/base-data-product/ProdSceneInfo.vue | 31 + src/views/fysp/support/JingAnNightConstruction.vue | 139 +++++- src/views/fysp/data-product/prod-step-change.js | 15 src/views/fysp/data-product/base-data-product/components/ProdQueryOpt.vue | 8 24 files changed, 869 insertions(+), 274 deletions(-) diff --git a/src/api/fysp/nightConstructionApi.js b/src/api/fysp/nightConstructionApi.js index 371448d..babbc8e 100644 --- a/src/api/fysp/nightConstructionApi.js +++ b/src/api/fysp/nightConstructionApi.js @@ -13,5 +13,18 @@ params: { cityCode, districtCode, page, perPage } }) .then((res) => res.data); + }, + + /** + * 鏇存柊宸ュ湴澶滈棿鏂藉伐璁稿彲璇� + * @param {*} param0 + * @returns + */ + updateRecord({ recordId, userId, sceneId }) { + return $fysp + .post(`nightwork/record`, undefined, { + params: { recordId, userId, sceneId } + }) + .then((res) => res.data); } }; diff --git a/src/components.d.ts b/src/components.d.ts index fdde43f..3d570e1 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -20,8 +20,11 @@ ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb'] ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem'] ElButton: typeof import('element-plus/es')['ElButton'] + ElCalendar: typeof import('element-plus/es')['ElCalendar'] ElCard: typeof import('element-plus/es')['ElCard'] ElCascader: typeof import('element-plus/es')['ElCascader'] + ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] + ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup'] ElCol: typeof import('element-plus/es')['ElCol'] ElCollapse: typeof import('element-plus/es')['ElCollapse'] ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem'] @@ -42,11 +45,13 @@ ElImageViewer: typeof import('element-plus/es')['ElImageViewer'] ElInput: typeof import('element-plus/es')['ElInput'] ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] + ElLink: typeof import('element-plus/es')['ElLink'] ElMain: typeof import('element-plus/es')['ElMain'] ElMenu: typeof import('element-plus/es')['ElMenu'] ElMenuItem: typeof import('element-plus/es')['ElMenuItem'] ElMenuItemGroup: typeof import('element-plus/es')['ElMenuItemGroup'] ElOption: typeof import('element-plus/es')['ElOption'] + ElPageHeader: typeof import('element-plus/es')['ElPageHeader'] ElPagination: typeof import('element-plus/es')['ElPagination'] ElPopover: typeof import('element-plus/es')['ElPopover'] ElRadio: typeof import('element-plus/es')['ElRadio'] @@ -54,6 +59,7 @@ ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] ElRow: typeof import('element-plus/es')['ElRow'] ElScrollbar: typeof import('element-plus/es')['ElScrollbar'] + ElSegmented: typeof import('element-plus/es')['ElSegmented'] ElSelect: typeof import('element-plus/es')['ElSelect'] ElSpace: typeof import('element-plus/es')['ElSpace'] ElStep: typeof import('element-plus/es')['ElStep'] @@ -67,6 +73,7 @@ ElTag: typeof import('element-plus/es')['ElTag'] ElText: typeof import('element-plus/es')['ElText'] ElTooltip: typeof import('element-plus/es')['ElTooltip'] + ElTransfer: typeof import('element-plus/es')['ElTransfer'] ElTree: typeof import('element-plus/es')['ElTree'] ElUpload: typeof import('element-plus/es')['ElUpload'] Footer: typeof import('./components/core/Footer.vue')['default'] diff --git a/src/components/SearchBar.vue b/src/components/SearchBar.vue index c3609f4..19f48c3 100644 --- a/src/components/SearchBar.vue +++ b/src/components/SearchBar.vue @@ -1,6 +1,6 @@ <template> <el-row class="layout"> - <el-col :span="10"> + <el-col :span="$slots.summary ? 10 : 24"> <el-form :inline="true" :model="formSearch"> <el-form-item label="鎬讳换鍔�"> <!-- <el-input v-model="formSearch.topTaskId" placeholder="鎬讳换鍔�" /> --> @@ -27,7 +27,7 @@ </el-form-item> </el-form> </el-col> - <el-col :span="14"> + <el-col :span="$slots.summary ? 14 : 0"> <el-row justify="end"> <slot name="summary"></slot> </el-row> @@ -85,7 +85,8 @@ ); const param = { topTask: task ? task.data : {}, - sceneTypeId: this.formSearch.scenetype.value + sceneTypeId: this.formSearch.scenetype.value, + sceneTypeName: this.formSearch.scenetype.label, }; // console.log(param); diff --git a/src/components/SideList.vue b/src/components/SideList.vue index 846be3d..a3a795c 100644 --- a/src/components/SideList.vue +++ b/src/components/SideList.vue @@ -1,147 +1,153 @@ <template> - <div v-if="legend" class="state-label"> - <el-input - v-model="filterText" - icon="Search" - style="width: 200px" - placeholder="鍏抽敭瀛楃瓫閫�" - clearable - /> - <el-tooltip placement="bottom-start" effect="dark"> - <template #content> - <el-space> - <el-space v-for="(item, index) in stateLabels" :key="index" :size="1"> - <el-icon :color="item.color"> - <component :is="item.icon"></component> - </el-icon> - {{ item.name }} - <!-- <el-text size="small">{{ item.name }}</el-text> --> + <div style="padding-right: 10px;"> + <div v-if="legend" class="state-label"> + <el-input + v-model="filterText" + icon="Search" + style="width: 180px" + placeholder="鍏抽敭瀛楃瓫閫�" + clearable + /> + <el-tooltip placement="bottom-start" effect="dark"> + <template #content> + <el-space> + <el-space + v-for="(item, index) in stateLabels" + :key="index" + :size="1" + > + <el-icon :color="item.color"> + <component :is="item.icon"></component> + </el-icon> + {{ item.name }} + <!-- <el-text size="small">{{ item.name }}</el-text> --> + </el-space> </el-space> - </el-space> - <br /> + <br /> + <el-space> + <el-space :size="1"> + <el-icon :size="16" color="var(--el-color-success)"> + <Avatar /> + </el-icon> + 姝e湪鎵ц宸℃煡 + </el-space> + <el-space :size="1"> + <el-icon :size="16" color="var(--el-color-info)"> + <Avatar /> + </el-icon> + 鏈墽琛� + </el-space> + </el-space> + </template> <el-space> - <el-space :size="1"> - <el-icon :size="16" color="var(--el-color-success)"> + <el-icon class="cursor-p" :size="16" color="var(--el-color-primary)" + ><QuestionFilled + /></el-icon> + <el-text size="small" class="cursor-p">瀹℃牳鐘舵�佸浘渚�</el-text> + </el-space> + </el-tooltip> + </div> + <el-tree + ref="treeRef" + class="el-tree" + v-loading="isLoading" + :data="dataList" + :props="defaultProps" + @node-click="handleNodeClick" + :filter-node-method="filterNode" + default-expand-all + highlight-current + check-on-click-node + empty-text="鏆傛棤璁板綍" + > + <template #default="{ node, data }"> + <slot :node="node" :data="data"> + <div + :class=" + data.selected + ? 'selected-tree-node custom-tree-node' + : 'custom-tree-node' + " + > + <el-icon + v-if="data.status == '姝e湪鎵ц'" + :size="16" + color="var(--el-color-success)" + style="margin-left: -16px" + > <Avatar /> </el-icon> - 姝e湪鎵ц宸℃煡 - </el-space> - <el-space :size="1"> - <el-icon :size="16" color="var(--el-color-info)"> + <el-icon + v-if="data.status == '鏈墽琛�'" + :size="16" + color="var(--el-color-info)" + style="margin-left: -16px" + > <Avatar /> </el-icon> - 鏈墽琛� - </el-space> - </el-space> - </template> - <el-space> - <el-icon class="cursor-p" :size="16" color="var(--el-color-primary)" - ><QuestionFilled - /></el-icon> - <el-text size="small" class="cursor-p">瀹℃牳鐘舵�佸浘渚�</el-text> - </el-space> - </el-tooltip> - </div> - <el-tree - ref="treeRef" - class="el-tree" - v-loading="isLoading" - :data="dataList" - :props="defaultProps" - @node-click="handleNodeClick" - :filter-node-method="filterNode" - default-expand-all - highlight-current - check-on-click-node - empty-text="鏆傛棤璁板綍" - > - <template #default="{ node, data }"> - <slot :node="node" :data="data"> - <div - :class=" - data.selected - ? 'selected-tree-node custom-tree-node' - : 'custom-tree-node' - " - > - <el-icon - v-if="data.status == '姝e湪鎵ц'" - :size="16" - color="var(--el-color-success)" - style="margin-left: -16px" - > - <Avatar /> - </el-icon> - <el-icon - v-if="data.status == '鏈墽琛�'" - :size="16" - color="var(--el-color-info)" - style="margin-left: -16px" - > - <Avatar /> - </el-icon> - <!-- <el-icon :color="stateLabels[data.type].color"> + <!-- <el-icon :color="stateLabels[data.type].color"> <component :is="stateLabels[data.type].icon"></component> </el-icon> --> - <el-icon - v-if="data.type == 0" - :size="16" - color="var(--el-color-info)" - > - <SuccessFilled /> - </el-icon> - <el-icon - v-else-if="data.type == 1" - :size="16" - color="var(--el-color-danger)" - > - <QuestionFilled /> - </el-icon> - <el-icon - v-else-if="data.type == 2" - :size="16" - color="var(--el-color-warning)" - > - <QuestionFilled /> - </el-icon> - <el-icon - v-else-if="data.type == 3" - :size="16" - color="var(--el-color-danger)" - > - <WarnTriangleFilled /> - </el-icon> - <el-icon - v-else-if="data.type == 4" - :size="16" - color="var(--el-color-danger)" - > - <WarningFilled /> - </el-icon> - <el-icon - v-else-if="data.type == 5" - :size="16" - color="var(--el-color-warning)" - > - <WarningFilled /> - </el-icon> - <el-icon - v-else-if="data.type == 6" - :size="16" - color="var(--el-color-success)" - > - <SuccessFilled /> - </el-icon> - <!-- <el-text>{{ node.label }}</el-text> --> - {{ node.label }} - <span v-if="data.count"> - {{ '_(' + data.count + ')' }} - <!-- <el-text size="small">鐐规</el-text>) --> - </span> - </div> - </slot> - </template> - </el-tree> + <el-icon + v-if="data.type == 0" + :size="16" + color="var(--el-color-info)" + > + <SuccessFilled /> + </el-icon> + <el-icon + v-else-if="data.type == 1" + :size="16" + color="var(--el-color-danger)" + > + <QuestionFilled /> + </el-icon> + <el-icon + v-else-if="data.type == 2" + :size="16" + color="var(--el-color-warning)" + > + <QuestionFilled /> + </el-icon> + <el-icon + v-else-if="data.type == 3" + :size="16" + color="var(--el-color-danger)" + > + <WarnTriangleFilled /> + </el-icon> + <el-icon + v-else-if="data.type == 4" + :size="16" + color="var(--el-color-danger)" + > + <WarningFilled /> + </el-icon> + <el-icon + v-else-if="data.type == 5" + :size="16" + color="var(--el-color-warning)" + > + <WarningFilled /> + </el-icon> + <el-icon + v-else-if="data.type == 6" + :size="16" + color="var(--el-color-success)" + > + <SuccessFilled /> + </el-icon> + <!-- <el-text>{{ node.label }}</el-text> --> + {{ node.label }} + <span v-if="data.count"> + {{ '_(' + data.count + ')' }} + <!-- <el-text size="small">鐐规</el-text>) --> + </span> + </div> + </slot> + </template> + </el-tree> + </div> </template> <script> diff --git a/src/components/ToolBar.vue b/src/components/ToolBar.vue index 29487a5..86d046c 100644 --- a/src/components/ToolBar.vue +++ b/src/components/ToolBar.vue @@ -60,7 +60,7 @@ </script> <style scoped> .layout { - /* background-color: beige; */ + background-color: white; height: var(--height-toolbar); border-bottom: 1px solid var(--el-color-info-light-7); box-shadow: 6px 4px 4px rgba(0, 0, 0, 0.12); diff --git a/src/components/core/BaseContentLayout.vue b/src/components/core/BaseContentLayout.vue index 3889435..dfd48a8 100644 --- a/src/components/core/BaseContentLayout.vue +++ b/src/components/core/BaseContentLayout.vue @@ -4,12 +4,12 @@ <slot name="header"></slot> </el-header> <el-container> - <el-aside class="el-aside" :style="'height: ' + mainHeight"> - <el-scrollbar :noresize="true" style="position: relative;"> + <el-aside class="el-aside" :style="{ height: mainHeight + 'px' }"> + <el-scrollbar :noresize="false"> <slot name="aside"></slot> </el-scrollbar> </el-aside> - <el-main class="el-main" :style="'height: ' + mainHeight"> + <el-main class="el-main" :style="{ height: mainHeight + 'px' }"> <slot name="main"></slot> </el-main> </el-container> @@ -18,10 +18,11 @@ <script> export default { + inject: ['contentMaxHeight'], // 鍙充晶鎿嶄綔鐣岄潰鍩虹甯冨眬 data() { return { - mainHeight: 'calc(100vh - 60px * 2 - var(--el-main-padding) * 2)' + mainHeight: this.contentMaxHeight.value }; }, methods: { @@ -30,9 +31,10 @@ if (this.$refs.headerRef) { const h1 = this.$refs.headerRef.$el.offsetHeight; const h = h1; - return `calc(100vh - ${h}px - 60px - var(--el-main-padding) * 2 + 6px)`; + return this.contentMaxHeight.value - h; + // return `calc(100vh - ${h}px - 60px - var(--el-main-padding) * 2 + 6px)`; } else { - return `calc(100vh - 60px * 2 - var(--el-main-padding) * 2)`; + return this.contentMaxHeight.value; } } }, @@ -58,10 +60,10 @@ .el-header { height: initial; - padding: 0 0 0px 0; + padding: 0 0 4px 0; /* background-color: rgb(216, 201, 201); */ /* border-bottom: 1px solid var(--el-color-info-light-7); */ - margin-bottom: 4px; + /* margin-bottom: 4px; */ } .el-main { @@ -69,7 +71,7 @@ /* background-color: whitesmoke; */ /* height: calc(100vh - 60px * 2 - 20px * 2); */ padding: initial; - padding-left: 20px; + padding-left: 10px; /* overflow: hidden; */ } </style> diff --git a/src/components/search-option/FYSearchBar.vue b/src/components/search-option/FYSearchBar.vue index e968e58..fb3eab6 100644 --- a/src/components/search-option/FYSearchBar.vue +++ b/src/components/search-option/FYSearchBar.vue @@ -1,7 +1,7 @@ <template> <el-form :inline="true" :size="size"> <slot name="options"></slot> - <el-form-item> + <el-form-item v-if="$slots.options"> <el-button icon="Search" type="primary" diff --git a/src/components/table/FYTable.vue b/src/components/table/FYTable.vue index b759ee0..a85de22 100644 --- a/src/components/table/FYTable.vue +++ b/src/components/table/FYTable.vue @@ -1,10 +1,10 @@ <template> <el-row ref="searchRef"> <FYSearchBar @search="onSearch"> - <template #options> + <template #options v-if="$slots.options"> <slot name="options"></slot> </template> - <template #buttons> + <template #buttons v-if="$slots.buttons"> <slot name="buttons"></slot> </template> </FYSearchBar> @@ -69,6 +69,7 @@ * 浣跨敤鏃堕渶瑕佸湪<slot #options>涓坊鍔犺嚜瀹氫箟鏌ヨ閫夐」锛屽湪<slot #table-column>涓坊鍔犺嚜瀹氫箟琛ㄦ牸鍒楋紝鍚屾椂瀹炵幇瑙﹀彂鍑芥暟search */ export default { + inject: ['contentMaxHeight'], props: { rowClassName: undefined, cellClassName: Function || String, @@ -86,6 +87,11 @@ default: () => [] }, totalCount: { + type: Number, + default: 0 + }, + // 棰濆鐨勯珮搴︼紝鐢ㄤ簬璁$畻琛ㄦ牸楂樺害 + extraHeight: { type: Number, default: 0 } @@ -130,26 +136,16 @@ if (nValue != oValue) { this.total = nValue; } + }, + extraHeight: { + handler(nValue, oValue) { + if (nValue != oValue) { + this.tableHeight = this.calcTableHeight(); + } + }, } }, - computed: { - cTableHeight() { - if (this.$refs.searchRef) { - const h1 = this.$refs.searchRef.$el.offsetHeight; - const h2 = this.$refs.paginationRef - ? this.$refs.paginationRef.$el.offsetHeight - : 0; - const h3 = this.$refs.expandRef.$el.offsetHeight; - const h4 = this.$refs.expand2Ref.offsetHeight; - - const h = h1 + h2 + h3 + h4; - // return `calc(100vh - ${h1}px - ${h2}px - var(--el-main-padding) * 2 - var(--el-header-height))`; - return `calc(100vh - ${h}px - 60px - var(--el-main-padding) * 2)`; - } else { - return '500'; - } - } - }, + computed: {}, methods: { /** * 琛ㄦ牸鏁版嵁鏌ヨ锛屼紶閫掍袱缁勫弬鏁帮紝鍒嗛〉淇℃伅鍜屽洖璋冨嚱鏁� @@ -186,9 +182,9 @@ const h3 = this.$refs.expandRef.$el.offsetHeight; const h4 = this.$refs.expand2Ref.offsetHeight; - const h = h1 + h2 + h3 + h4; - // return `calc(100vh - ${h1}px - ${h2}px - var(--el-main-padding) * 2 - var(--el-header-height))`; - return `calc(100vh - ${h}px - 60px - var(--el-main-padding) * 2)`; + const h = h1 + h2 + h3 + h4 + this.extraHeight; + return this.contentMaxHeight.value - h + 'px'; + // return `calc(100vh - ${h}px - 60px - var(--el-main-padding) * 2)`; }, tableRowClassName({ row }) { if (this.rowClassName) { @@ -220,7 +216,7 @@ mounted() { this.tableHeight = this.calcTableHeight(); this.onSearch(); - }, + } }; </script> diff --git a/src/router/index.js b/src/router/index.js index 5d81136..c229675 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -93,7 +93,7 @@ // 鍩虹浜у搧-鍦烘櫙娓呭崟 path: 'scene', name: 'ProdSceneInfo', - meta: { keepAlive: false, key: 'ProdManage' }, + meta: { keepAlive: true, key: 'ProdManage' }, component: () => import( '@/views/fysp/data-product/base-data-product/ProdSceneInfo.vue' @@ -103,7 +103,7 @@ // 鍩虹浜у搧-瑙勮寖鎬ц瘎浼� path: 'evaluate', name: 'ProdEvaluationInfo', - meta: { keepAlive: false, key: 'ProdManage' }, + meta: { keepAlive: true, key: 'ProdManage' }, component: () => import( '@/views/fysp/data-product/base-data-product/ProdEvaluationInfo.vue' @@ -113,7 +113,7 @@ // 鍩虹浜у搧-宸℃煡淇℃伅 path: 'inspection', name: 'ProdInspectionInfo', - meta: { keepAlive: false, key: 'ProdManage' }, + meta: { keepAlive: true, key: 'ProdManage' }, component: () => import( '@/views/fysp/data-product/base-data-product/ProdInspectionInfo.vue' @@ -123,7 +123,7 @@ // 鍩虹浜у搧-鐩戞祴鏁版嵁 path: 'monitordata', name: 'ProdMonitorDataInfo', - meta: { keepAlive: false, key: 'ProdManage' }, + meta: { keepAlive: true, key: 'ProdManage' }, component: () => import( '@/views/fysp/data-product/base-data-product/ProdMonitorDataInfo.vue' @@ -323,8 +323,8 @@ ]; const router = createRouter({ - history: createWebHistory(import.meta.env.BASE_URL), - // history: createWebHashHistory(), + // history: createWebHistory(import.meta.env.BASE_URL), + history: createWebHashHistory(), routes: routes }); diff --git a/src/views/HomePage.vue b/src/views/HomePage.vue index 83ce519..65add8b 100644 --- a/src/views/HomePage.vue +++ b/src/views/HomePage.vue @@ -1,11 +1,11 @@ <template> <el-container class="el-container"> - <el-aside class="el-aside" - ><SiderMenu :collapse="isCollapsed" @nav-page="navPage"></SiderMenu - ></el-aside> + <el-aside class="el-aside"> + <SiderMenu :collapse="isCollapsed" @nav-page="navPage"></SiderMenu> + </el-aside> <el-container> - <el-header class="el-header" - ><Header + <el-header ref="headerRef" class="el-header"> + <Header :navTitles="navTitles" :collapse="isCollapsed" @collapsed-sider="collapsedSider" @@ -13,7 +13,13 @@ ></el-header> <el-main class="el-main"> <el-scrollbar> - <div class="el-main__content"> + <div + class="el-main__content" + :style="{ + maxHeight: contentMaxHeight + 'px', + padding: mainPadding + 'px' + }" + > <Content></Content> <!-- <el-backtop target=".el-main .el-scrollbar__wrap" @@ -34,11 +40,16 @@ </template> <script> +import { computed } from 'vue'; + export default { data() { return { isCollapsed: false, - navTitles: [] + navTitles: [], + headerHeight: 60, + mainPadding: 10, + contentMaxHeight: NaN }; }, methods: { @@ -48,6 +59,18 @@ navPage(titles) { this.navTitles = titles; } + }, + mounted() { + this.headerHeight = this.$refs.headerRef.$el.offsetHeight; + this.contentMaxHeight = + window.innerHeight - this.headerHeight - this.mainPadding * 2; + }, + provide() { + return { + headerHeight: computed(() => this.headerHeight), + mainPadding: computed(() => this.mainPadding), + contentMaxHeight: computed(() => this.contentMaxHeight) + }; } }; </script> @@ -74,8 +97,10 @@ } .el-main__content { - padding: var(--el-main-padding) calc(var(--el-main-padding) / 2); - max-height: calc(100vh - 60px - var(--el-main-padding) * 2); + /* --main-padding: 10px; */ + /* padding: var(--main-padding) calc(var(--main-padding) / 2); */ + /* padding: var(--main-padding); */ + /* max-height: calc(100vh - 60px - var(--main-padding) * 2); */ /* background-color: aqua; */ /* overflow: auto; */ } diff --git a/src/views/fysp/check/ProCheck.vue b/src/views/fysp/check/ProCheck.vue index a7dfec4..d47f6a0 100644 --- a/src/views/fysp/check/ProCheck.vue +++ b/src/views/fysp/check/ProCheck.vue @@ -23,16 +23,14 @@ <template #main> <el-scrollbar> <ToolBar + ref="toolBarRef" + class="toolbar-sticky" :title="curSubtask.title" :descriptions="proStatus" :buttons="buttons" :loading="mainLoading" ></ToolBar> - <el-scrollbar - v-if="curProList.length > 0" - class="scrollbar-inner" - v-loading="mainLoading" - > + <div v-if="curProList.length > 0" v-loading="mainLoading"> <CompProblemCard :key="i" v-for="(p, i) in curProList" @@ -43,7 +41,7 @@ @submit="updateSubtask" @check="handleProblemCheck" ></CompProblemCard> - </el-scrollbar> + </div> <el-empty v-else description="鏆傛棤闂" v-loading="mainLoading" /> </el-scrollbar> </template> @@ -290,4 +288,10 @@ .scrollbar-inner { height: calc(100vh - 60px * 2 - 20px * 2 - var(--height-toolbar)); } + +.toolbar-sticky { + position: sticky; + z-index: 2; + top: 0; +} </style> diff --git a/src/views/fysp/config/device/CompInfoSearch.vue b/src/views/fysp/config/components/CompInfoSearch.vue similarity index 80% rename from src/views/fysp/config/device/CompInfoSearch.vue rename to src/views/fysp/config/components/CompInfoSearch.vue index bee891b..fc88f63 100644 --- a/src/views/fysp/config/device/CompInfoSearch.vue +++ b/src/views/fysp/config/components/CompInfoSearch.vue @@ -1,12 +1,12 @@ <template> <!-- <div v-if="modelValue"> --> - <el-divider content-position="left">閫夋嫨{{ label }}</el-divider> - <div class="select-box"> - <div> - <el-text size="small" type="info">褰撳墠閫夋嫨</el-text> - </div> - <slot name="selected" :row="modelValue"></slot> + <el-divider content-position="left">閫夋嫨{{ label }}</el-divider> + <div class="select-box"> + <div> + <el-text size="small" type="info">褰撳墠閫夋嫨</el-text> </div> + <slot name="selected" :row="modelValue"></slot> + </div> <!-- </div> --> <el-divider content-position="left">{{ label }}妫�绱�</el-divider> <FYSearchBar @search="search" :loading="loading"> @@ -15,7 +15,7 @@ label="" :placeholder="placeholder" v-model:value="searchText" - width="200px" + :width="searchTextWidth" ></FYOptionText> </template> </FYSearchBar> @@ -27,6 +27,7 @@ </div> </el-space> </el-scrollbar> + <el-empty v-else description="鏃犺褰�" /> </div> <el-pagination v-if="pageShow && dataList.length > 0" @@ -64,6 +65,10 @@ type: String, default: '杈撳叆鍏抽敭瀛楁绱�' }, + searchTextWidth: { + type: String, + default: '200px' + }, // 鏄惁鏄剧ず鍒嗛〉 pageShow: { type: Boolean, @@ -75,7 +80,9 @@ default: () => { return [10, 20, 50, 100]; } - } + }, + // 榛樿鎼滅储鏂囨湰 + defaultText: String }, emits: ['search', 'update:modelValue'], data() { @@ -86,7 +93,19 @@ loading: false }; }, - watch: {}, + watch: { + defaultText: { + handler(newVal) { + if (newVal) { + this.searchText = newVal; + setTimeout(() => { + this.search(); + }, 500); + } + }, + immediate: true + } + }, methods: { search() { this.loading = true; diff --git a/src/views/fysp/config/components/CompInfoSearchFysp.vue b/src/views/fysp/config/components/CompInfoSearchFysp.vue new file mode 100644 index 0000000..cd68241 --- /dev/null +++ b/src/views/fysp/config/components/CompInfoSearchFysp.vue @@ -0,0 +1,72 @@ +<template> + <CompInfoSearch + label="鐩戠鐢ㄦ埛" + placeholder="杈撳叆鐢ㄦ埛鍚嶇О" + @search="searchSVUser" + > + <template #selected="{ row }"> + <div> + <el-text>缂栧彿锛歿{ row?.svUserId }}</el-text> + </div> + <el-space> + <el-text>鍚嶇О锛歿{ row?.svUserName }}</el-text> + <el-button + v-show="row?.svUserName" + type="primary" + icon="DocumentCopy" + text + circle + @click="copySVUser(row?.svUserName)" + /> + </el-space> + </template> + <template #default="{ row, click }"> + <ItemUser :item="row" @add="selectSVUser(row, click)" /> + </template> + </CompInfoSearch> +</template> +<script setup> +import CompInfoSearch from './CompInfoSearch.vue'; +import { useCloned } from '@vueuse/core'; +import svUserApi from '@/api/fysp/userApi'; + +const props = defineProps({ + // 妫�绱㈣寖鍥达紙鍖呭惈琛屾斂鍖哄垝銆佸満鏅被鍨嬶級 + area: Object +}); + +// 鏌ヨ鐩戠鐢ㄦ埛 +function searchSVUser(param, callback) { + const { text, page, pageSize } = param; + const { cloned: area } = useCloned(props.area); + area.value.sceneName = text; + return svUserApi + .searchUser(area.value, text, page, pageSize) + .then((res) => { + if (res.success) { + const l = res.data.map((value) => { + return { + ...value, + district: value.remark + }; + }); + callback({ + data: l, + total: res.head.totalCount + }); + } + }) + .finally(() => { + callback(); + }); +} + +function selectSVUser(row, click) { + const p = { + svUserId: row.guid, + svUserName: row.realname, + ...row + }; + click(p); +} +</script> diff --git a/src/views/fysp/config/device/CompDeviceMatchEdit.vue b/src/views/fysp/config/device/CompDeviceMatchEdit.vue index a981b43..be4f751 100644 --- a/src/views/fysp/config/device/CompDeviceMatchEdit.vue +++ b/src/views/fysp/config/device/CompDeviceMatchEdit.vue @@ -94,7 +94,7 @@ <script> import { useCloned } from '@vueuse/core'; -import CompInfoSearch from './CompInfoSearch.vue'; +import CompInfoSearch from '../components/CompInfoSearch.vue'; import tzUserApi from '@/api/fytz/userApi'; import svUserApi from '@/api/fysp/userApi'; import userMapApi from '@/api/fysp/userMapApi'; diff --git a/src/views/fysp/data-product/base-data-product/ProdEvaluationInfo.vue b/src/views/fysp/data-product/base-data-product/ProdEvaluationInfo.vue index dc19bf6..c9c31d5 100644 --- a/src/views/fysp/data-product/base-data-product/ProdEvaluationInfo.vue +++ b/src/views/fysp/data-product/base-data-product/ProdEvaluationInfo.vue @@ -1,4 +1,98 @@ <template> - 1 + <BaseProdProcess + v-model:active="active" + @onStep1="onStep1" + @onStep2="onStep2" + @onStep3="onStep3" + :loading="loading" + > + <template #step2="{ contentHeight }"> + <el-table + id="prod-evaluation-table" + :data="tableData" + v-loading="loading" + :height="contentHeight + 'px'" + table-layout="fixed" + :show-overflow-tooltip="true" + size="small" + border + > + <el-table-column fixed="left" prop="index" label="缂栧彿" width="50"> + </el-table-column> + <el-table-column + fixed="left" + prop="subTask.scensename" + label="鍚嶇О" + :show-overflow-tooltip="true" + min-width="200" + > + </el-table-column> + <el-table-column + prop="subTask.planstarttime" + label="宸℃煡鏃堕棿" + :formatter="timeFormat" + width="90" + /> + <!-- <el-table-column prop="provincename" label="鐪�" width="90" /> + <el-table-column prop="cityname" label="甯�" width="90" /> + <el-table-column prop="districtname" label="鍖哄幙" width="90" /> --> + <el-table-column prop="evaluate.townname" label="琛楅亾" width="80" /> + <el-table-column + prop="evaluate.resultscorebef" + label="璇勫垎" + width="60" + /> + <el-table-column prop="scoreLevel" label="瑙勮寖鎬�" width="70" /> + <el-table-column + prop="evaluate.updatedate" + label="鏇存柊鏃堕棿" + width="140" + :formatter="timeFormat" + /> + </el-table> + </template> + </BaseProdProcess> </template> -<script></script> \ No newline at end of file +<script setup> +import { ref, inject } from 'vue'; +import dayjs from 'dayjs'; +import BaseProdProcess from '@/views/fysp/data-product/base-data-product/components/BaseProdProcess.vue'; +import dataprodbaseApi from '@/api/fysp/dataprodbaseApi.js'; +import { conversionFromTable } from '@/utils/excel'; +import { useProdStepChange } from '@/views/fysp/data-product/prod-step-change.js'; + +const { active, changeActive } = useProdStepChange(); +const loading = ref(false); +const tableData = ref([]); + +function onStep1(opt) { + loading.value = true; + dataprodbaseApi + .fetchProdEvaluateInfo(opt) + .then((res) => { + if (res.success) { + tableData.value = res.data; + } + changeActive(); + }) + .finally(() => { + loading.value = false; + }); +} + +function onStep2() { + changeActive(); +} + +function onStep3(val) { + if (val.downloadType == '1') { + loading.value = true; + conversionFromTable('prod-evaluation-table', '瑙勮寖鎬ц瘎浼版竻鍗�'); + loading.value = false; + } +} + +function timeFormat(row, column, cellValue, index) { + return dayjs(cellValue).format('YYYY-MM-DD'); +} +</script> diff --git a/src/views/fysp/data-product/base-data-product/ProdInspectionInfo.vue b/src/views/fysp/data-product/base-data-product/ProdInspectionInfo.vue index dc19bf6..10bd091 100644 --- a/src/views/fysp/data-product/base-data-product/ProdInspectionInfo.vue +++ b/src/views/fysp/data-product/base-data-product/ProdInspectionInfo.vue @@ -1,4 +1,104 @@ <template> - 1 + <BaseProdProcess + v-model:active="active" + @onStep1="onStep1" + @onStep2="onStep2" + @onStep3="onStep3" + :loading="loading" + > + <template #step2="{ contentHeight }"> + <el-table + id="prod-inspection-table" + :data="tableData" + v-loading="loading" + :height="contentHeight + 'px'" + table-layout="fixed" + :show-overflow-tooltip="true" + size="small" + border + > + <el-table-column fixed="left" prop="index" label="缂栧彿" width="50"> + </el-table-column> + <el-table-column + fixed="left" + prop="subTask.scensename" + label="鍚嶇О" + :show-overflow-tooltip="true" + min-width="200" + > + </el-table-column> + <el-table-column + prop="subTask.planstarttime" + label="宸℃煡鏃堕棿" + :formatter="timeFormat" + width="90" + /> + <!-- <el-table-column prop="provincename" label="鐪�" width="90" /> + <el-table-column prop="cityname" label="甯�" width="90" /> + <el-table-column prop="districtname" label="鍖哄幙" width="90" /> --> + <el-table-column prop="subTask.townname" label="琛楅亾" width="80" /> + <el-table-column + prop="problems.length" + label="闂鏁�" + width="60" + /> + <el-table-column prop="scoreLevel" label="闂鎽樿" width="70" /> + <el-table-column + prop="evaluate.resultscorebef" + label="鏈暣鏀规暟" + width="60" + /> + <el-table-column prop="scoreLevel" label="鏈暣鏀归棶棰�" width="70" /> + <el-table-column + prop="evaluate.updatedate" + label="鏇存柊鏃堕棿" + width="140" + :formatter="timeFormat" + /> + </el-table> + </template> + </BaseProdProcess> </template> -<script></script> \ No newline at end of file +<script setup> +import { ref, inject } from 'vue'; +import dayjs from 'dayjs'; +import BaseProdProcess from '@/views/fysp/data-product/base-data-product/components/BaseProdProcess.vue'; +import dataprodbaseApi from '@/api/fysp/dataprodbaseApi.js'; +import { conversionFromTable } from '@/utils/excel'; +import { useProdStepChange } from '@/views/fysp/data-product/prod-step-change.js'; + +const { active, changeActive } = useProdStepChange(); +const loading = ref(false); +const tableData = ref([]); + +function onStep1(opt) { + loading.value = true; + dataprodbaseApi + .fetchProdInspectionInfo(opt) + .then((res) => { + if (res.success) { + tableData.value = res.data; + } + changeActive(); + }) + .finally(() => { + loading.value = false; + }); +} + +function onStep2() { + changeActive(); +} + +function onStep3(val) { + if (val.downloadType == '1') { + loading.value = true; + conversionFromTable('prod-inspection-table', '鏁存敼娓呭崟'); + loading.value = false; + } +} + +function timeFormat(row, column, cellValue, index) { + return dayjs(cellValue).format('YYYY-MM-DD'); +} +</script> diff --git a/src/views/fysp/data-product/base-data-product/ProdManage.vue b/src/views/fysp/data-product/base-data-product/ProdManage.vue index 0f1ff6b..e04d292 100644 --- a/src/views/fysp/data-product/base-data-product/ProdManage.vue +++ b/src/views/fysp/data-product/base-data-product/ProdManage.vue @@ -5,7 +5,6 @@ default-active="scene" ellipsis mode="horizontal" - style="max-width: 600px; background-color: aliceblue" > <el-menu-item v-for="item in menu" @@ -16,7 +15,7 @@ > </el-menu> </el-affix> - <router-view v-slot="{ Component, route }" :style="'height: ' + height"> + <router-view v-slot="{ Component, route }" :style="{ height: height + 'px' }"> <keep-alive> <component v-if="route.meta.keepAlive" @@ -28,14 +27,16 @@ </router-view> </template> <script setup> -import { ref, onMounted, provide } from 'vue'; +import { ref, onMounted, provide, inject, computed } from 'vue'; import { useRouter, useRoute } from 'vue-router'; + +const contentMaxHeight = inject('contentMaxHeight'); const router = useRouter(); const route = useRoute(); const menuRef = ref(null); -const height = ref('calc(100vh - 64px)'); +const height = ref(contentMaxHeight.value); const menu = ref([ { @@ -48,7 +49,7 @@ path: 'evaluate' }, { - name: '宸℃煡淇℃伅', + name: '鏁存敼娓呭崟', path: 'inspection' }, { @@ -67,7 +68,8 @@ function calcTableHeight() { const h = menuRef.value.$el.offsetHeight; - return `calc(100vh - ${h}px - 60px - var(--el-main-padding) * 2)`; + return contentMaxHeight.value - h; + // return `calc(100vh - ${h}px - 60px - var(--el-main-padding) * 2)`; } onMounted(() => { @@ -75,6 +77,9 @@ }); // 鎻愪緵缁欏唴閮ㄧ粍浠惰鍥炬渶澶ч珮搴� -provide('viewHeight', height); +provide( + 'viewHeight', + computed(() => height.value) +); </script> <style scoped></style> diff --git a/src/views/fysp/data-product/base-data-product/ProdSceneInfo.vue b/src/views/fysp/data-product/base-data-product/ProdSceneInfo.vue index 0f817a5..ef1323e 100644 --- a/src/views/fysp/data-product/base-data-product/ProdSceneInfo.vue +++ b/src/views/fysp/data-product/base-data-product/ProdSceneInfo.vue @@ -2,6 +2,8 @@ <BaseProdProcess v-model:active="active" @onStep1="onStep1" + @onStep2="onStep2" + @onStep3="onStep3" :loading="loading" > <!-- <template #step1> @@ -9,15 +11,16 @@ </template> --> <template #step2="{ contentHeight }"> <el-table + id="prod-scene-table" :data="tableData" v-loading="loading" - :height="viewHeight" + :height="contentHeight + 'px'" table-layout="fixed" :show-overflow-tooltip="true" size="small" border > - <el-table-column fixed="left" prop="index" label="缂栧彿" width="40"> + <el-table-column fixed="left" prop="index" label="缂栧彿" width="50"> </el-table-column> <el-table-column fixed="left" @@ -35,6 +38,8 @@ <el-table-column prop="districtname" label="鍖哄幙" width="90" /> --> <el-table-column prop="townname" label="琛楅亾" width="110" /> <el-table-column prop="location" label="鍦板潃" width="200" /> + <el-table-column prop="contacts" label="鑱旂郴浜�" width="70" /> + <el-table-column prop="contactst" label="鐢佃瘽" width="96" /> <!-- <el-table-column prop="longitude" label="缁忓害" width="110" /> <el-table-column prop="latitude" label="绾害" width="110" /> --> <!-- <el-table-column @@ -54,16 +59,12 @@ import BaseProdProcess from '@/views/fysp/data-product/base-data-product/components/BaseProdProcess.vue'; import ProdQueryOpt from '@/views/fysp/data-product/base-data-product/components/ProdQueryOpt.vue'; import dataprodbaseApi from '@/api/fysp/dataprodbaseApi.js'; +import { conversionFromTable } from '@/utils/excel'; +import { useProdStepChange } from '@/views/fysp/data-product/prod-step-change.js'; -const active = ref(1); +const { active, changeActive } = useProdStepChange(); const loading = ref(false); const tableData = ref([]); -const viewHeight = inject('viewHeight'); - -function changeActive() { - active.value++; - active.value = active.value > 3 ? 1 : active.value; -} function onStep1(opt) { loading.value = true; @@ -84,6 +85,18 @@ }); } +function onStep2() { + changeActive(); +} + +function onStep3(val) { + if (val.downloadType == '1') { + loading.value = true; + conversionFromTable('prod-scene-table', '宸℃煡鍦烘櫙娓呭崟'); + loading.value = false; + } +} + function timeFormat(row, column, cellValue, index) { return dayjs(cellValue).format('YYYY-MM-DD HH:mm:ss'); } diff --git a/src/views/fysp/data-product/base-data-product/components/BaseProdProcess.vue b/src/views/fysp/data-product/base-data-product/components/BaseProdProcess.vue index 356a41d..8d533e7 100644 --- a/src/views/fysp/data-product/base-data-product/components/BaseProdProcess.vue +++ b/src/views/fysp/data-product/base-data-product/components/BaseProdProcess.vue @@ -22,7 +22,7 @@ <div v-show="showStep1Thumbnail" class="prod-thumbnail-wrapper" - :style="{ height: viewHeight }" + :style="{ height: viewHeight + 'px' }" @click="changeActive(1)" > <div class="prod-thumbnail">鈶犱慨鏀归�夐」</div> @@ -38,6 +38,9 @@ <div v-show="showStep2Content"> <div ref="titleRef" class="prod-title"> <el-text tag="b" size="large">鏁版嵁浜у搧棰勮</el-text> + <el-button type="primary" @click="$emit('onStep2')"> + 涓嬭浇鏁版嵁浜у搧 + </el-button> </div> <slot name="step2" :contentHeight="contentHeight"></slot> </div> @@ -49,7 +52,7 @@ <div v-show="showStep2Thumbnail" class="prod-thumbnail-wrapper" - :style="{ height: viewHeight }" + :style="{ height: viewHeight + 'px' }" @click="changeActive(2)" > <div @@ -74,7 +77,11 @@ <slot name="step3"></slot> </template> <template v-else> - <ProdDownload></ProdDownload> + <ProdDownload + :loading="loading" + :queryOpt="queryOpt" + @submit="onDownload" + ></ProdDownload> </template> </div> </transition> @@ -85,7 +92,7 @@ <div v-show="showStep3Thumbnail" class="prod-thumbnail-wrapper" - :style="{ height: viewHeight }" + :style="{ height: viewHeight + 'px' }" @click="changeActive(3)" > <div @@ -102,7 +109,7 @@ </el-row> </template> <script setup> -import { computed, inject, ref, watch, onMounted } from 'vue'; +import { computed, inject, ref, watch, onMounted, onUnmounted } from 'vue'; import { unCalc } from '@/utils/css-util'; import ProdQueryOpt from '@/views/fysp/data-product/base-data-product/components/ProdQueryOpt.vue'; import ProdDownload from '@/views/fysp/data-product/base-data-product/components/ProdDownload.vue'; @@ -118,9 +125,10 @@ } }); -const emit = defineEmits(['update:active', 'onStep1']); +const emit = defineEmits(['update:active', 'onStep1', 'onStep2', 'onStep3']); -const viewHeight = inject('viewHeight'); +const contentMaxHeight = inject('contentMaxHeight'); +const viewHeight = inject('viewHeight', contentMaxHeight.value); const btnDisabled = ref(false); @@ -128,13 +136,13 @@ const contentHeight = ref('50vh'); function calContentHeight() { - console.log(titleRef.value.offsetHeight); - contentHeight.value = `calc(${unCalc(viewHeight.value)} - ${ - titleRef.value?.offsetHeight || 0 - }px)`; - console.log(contentHeight.value); - + // console.log(titleRef.value.offsetHeight); + contentHeight.value = viewHeight.value - (titleRef.value?.offsetHeight || 0); + // console.log(contentHeight.value); } + +// 鏁版嵁浜у搧鐢熸垚閫夐」 +const queryOpt = ref({}); // 姝ラ寮曠敤 const step1Ref = ref(null); @@ -217,7 +225,11 @@ } function onSearch(opt) { + queryOpt.value = opt; emit('onStep1', opt); +} +function onDownload(val) { + emit('onStep3', val); } function changeActive(index) { let isAnimate = false; @@ -234,8 +246,21 @@ // emit('update:active', index); } +let resizeObserver = null; + onMounted(() => { - calContentHeight(); + if (titleRef.value) { + resizeObserver = new ResizeObserver(() => { + calContentHeight(); + }); + resizeObserver.observe(titleRef.value); + } +}); +// 鍦ㄧ粍浠跺嵏杞芥椂娓呯悊 +onUnmounted(() => { + if (resizeObserver && titleRef.value) { + resizeObserver.unobserve(titleRef); + } }); </script> <style scoped> @@ -263,7 +288,10 @@ } .prod-title { - padding: 10px; + padding: 20px; + display: flex; + justify-content: space-between; + align-items: center; } .prod-thumbnail-wrapper { @@ -285,7 +313,7 @@ text-orientation: upright; letter-spacing: 8px; font-size: 18px; - font-weight: 500; + font-weight: 600; border-top-left-radius: 4px; border-bottom-left-radius: 4px; cursor: pointer; diff --git a/src/views/fysp/data-product/base-data-product/components/ProdDownload.vue b/src/views/fysp/data-product/base-data-product/components/ProdDownload.vue index 54642c5..2ee4fa6 100644 --- a/src/views/fysp/data-product/base-data-product/components/ProdDownload.vue +++ b/src/views/fysp/data-product/base-data-product/components/ProdDownload.vue @@ -1,2 +1,68 @@ -<template>ProdDownload</template> -<script setup></script> +<template> + <el-card shadow="never"> + <template #header> + <div><el-text tag="b" size="large">鏁版嵁浜у搧涓嬭浇</el-text></div> + </template> + <el-form :inline="false" label-position="left" label-width="150px"> + <el-form-item label="鍖哄幙"> + <el-text>{{ queryOpt.districtName }}</el-text> + </el-form-item> + <el-form-item label="鏃堕棿鑼冨洿"> + <el-text>{{ queryOpt.startTime }} 鑷� {{ queryOpt.endTime }}</el-text> + </el-form-item> + <el-form-item label="鍦烘櫙绫诲瀷"> + <el-text>{{ queryOpt.sceneTypeName }}</el-text> + </el-form-item> + <el-form-item label="浜у搧褰㈠紡"> + <el-radio-group v-model="downloadType"> + <el-radio value="1"> Excel琛ㄥ崟 </el-radio> + <el-radio value="2" :disabled="true"> Word鏂囨。 </el-radio> + </el-radio-group> + </el-form-item> + </el-form> + <template #footer> + <el-row justify="end"> + <el-button + type="primary" + size="default" + :loading="loading" + @click="submit" + icon="Download" + >涓嬭浇</el-button + > + </el-row> + </template> + </el-card> +</template> +<script setup> +import { ref, computed } from 'vue'; +import dayjs from 'dayjs'; +import scene_1 from '@/assets/image/scene_1.png'; + +const props = defineProps({ + // 鏁版嵁浜у搧鐢熸垚閫夐」 + queryOpt: { + type: Object, + default: () => {} + }, + loading: { + type: Boolean, + default: false + } +}); +const emit = defineEmits(['submit']); + +const downloadType = ref('1'); + +const submit = () => { + emit('submit', { + downloadType: downloadType.value + }); +}; +</script> +<style scoped> +/* .image { + width: 200px; + height: 200px; +} */ +</style> diff --git a/src/views/fysp/data-product/base-data-product/components/ProdQueryOpt.vue b/src/views/fysp/data-product/base-data-product/components/ProdQueryOpt.vue index 8f9618d..a1ac625 100644 --- a/src/views/fysp/data-product/base-data-product/components/ProdQueryOpt.vue +++ b/src/views/fysp/data-product/base-data-product/components/ProdQueryOpt.vue @@ -12,7 +12,7 @@ > </SearchBar> <template #footer> - <el-row v-show="active" justify="space-around"> + <el-row v-show="active" justify="end"> <el-button type="primary" size="default" @@ -49,16 +49,22 @@ const search = (options) => { const opt = { topTaskId: options.topTask.tguid, + topTaskName: options.topTask.name, provinceCode: options.topTask.provincecode, + provinceName: options.topTask.provincename, cityCode: options.topTask.citycode, + cityName: options.topTask.cityname, districtCode: options.topTask.districtcode, + districtName: options.topTask.districtname, townCode: options.topTask.towncode, + townName: options.topTask.townname, startTime: dayjs(options.topTask.starttime).format('YYYY-MM-DD HH:mm:ss'), endTime: dayjs(options.topTask.endtime) .add(1, 'day') .add(-1, 'second') .format('YYYY-MM-DD HH:mm:ss'), sceneTypeId: options.sceneTypeId, + sceneTypeName: options.sceneTypeName, needCache: true }; emit('submit', opt); diff --git a/src/views/fysp/data-product/prod-step-change.js b/src/views/fysp/data-product/prod-step-change.js new file mode 100644 index 0000000..a6630ab --- /dev/null +++ b/src/views/fysp/data-product/prod-step-change.js @@ -0,0 +1,15 @@ +import { ref } from 'vue'; +/** + * 鏁版嵁浜у搧姝ラ鍒囨崲 + */ +export function useProdStepChange() { + const active = ref(1); + function changeActive() { + active.value++; + active.value = active.value > 3 ? 1 : active.value; + } + return { + active, + changeActive + }; +} diff --git a/src/views/fysp/support/JingAnNightConstruction.vue b/src/views/fysp/support/JingAnNightConstruction.vue index d8c5b2e..c4066bf 100644 --- a/src/views/fysp/support/JingAnNightConstruction.vue +++ b/src/views/fysp/support/JingAnNightConstruction.vue @@ -1,9 +1,12 @@ <template> - <FYTable @search="onSearch"> - <template #options> </template> - - <template #buttons> </template> - + <FYTable + :data="data" + :total-count="total" + @search="onSearch" + :extraHeight="tabsHeaderHeight" + > + <!-- <template #options> </template> + <template #buttons> </template> --> <template #table-column> <el-table-column fixed="left" @@ -48,40 +51,72 @@ {{ $fm.formatYMD(row.ncCreateTime) }} </template> </el-table-column> --> - <el-table-column prop="ncUserId" label="鍖归厤鐢ㄦ埛" width="110"> + <el-table-column prop="ncUserId" label="鍖归厤鐢ㄦ埛"> <template #default="{ row }"> - <el-text v-loading="row._loading">{{ - row._user ? row._user.realName : '鏈尮閰�' - }}</el-text> + <el-text + :loading="row._loading" + :type="row._user ? 'primary' : 'danger'" + >{{ row._user ? row._user.realname : '鏈尮閰�' }}</el-text + > </template> </el-table-column> - <el-table-column fixed="right" label="鎿嶄綔" width="160"> - <template #default="scope"> + <el-table-column fixed="right" label="鎿嶄綔" width="80"> + <template #default="{ row }"> <el-button - :loading="scope.row.loading1" + :disabled="row._loading" type="default" size="small" - @click="itemEdit(scope)" + @click="itemEdit(row)" >缂栬緫</el-button - > - <el-button - :loading="scope.row.loading2" - :type="scope.row.extension1 != '0' ? 'danger' : 'primary'" - size="small" - @click="itemActive(scope)" - >{{ scope.row.extension1 != '0' ? '涓嬬嚎' : '涓婄嚎' }}</el-button > </template> </el-table-column> </template> </FYTable> + <el-dialog v-model="dialog" destroy-on-close> + <CompInfoSearchFysp + v-model="selectedSVUser" + :area="area" + :defaultText="defaultText" + searchTextWidth="400px" + /> + <template #footer> + <el-button @click="dialog = false">鍙栨秷</el-button> + <el-button type="primary" @click="submit" :disabled="!selectedSVUser" + >纭畾</el-button + > + </template> + </el-dialog> </template> <script setup> -import { ref } from 'vue'; +import { ref, inject, computed } from 'vue'; import nightConstructionApi from '@/api/fysp/nightConstructionApi'; import userApi from '@/api/fysp/userApi'; +import CompInfoSearchFysp from '@/views/fysp/config/components/CompInfoSearchFysp.vue'; +import { ElMessage } from 'element-plus'; +const tabsHeaderHeight = inject('tabsHeaderHeight', 0); + +// 澶滈棿鏂藉伐璁板綍鍙婃�绘暟 const data = ref([]); +const total = ref(0); + +// 澶滈棿鏂藉伐璁板綍鍖归厤寮圭獥 +const dialog = ref(false); +const selectedSVUser = ref(null); +const selectedRow = ref(null); +const area = ref({ + provincecode: '31', + provincename: '涓婃捣甯�', + citycode: '3100', + cityname: '涓婃捣甯�', + districtcode: '310106', + districtname: '闈欏畨鍖�', + scensetypeid: '1' +}); +const defaultText = computed(() => { + return selectedRow.value?.ncItemName || undefined; +}); function onSearch(page, callback) { return nightConstructionApi @@ -93,17 +128,61 @@ }) .then((res) => { if (res.success) { - res.data.forEach((d) => { - res.data._loading = true; - userApi.getUserById(d.ncUserId).then((res1) => { - res.data._user = res1; - }); + data.value = res.data; + data.value.forEach((d) => { + d._loading = true; + if (d.ncUserId) { + userApi + .getUserById(d.ncUserId) + .then((res1) => { + d._user = res1; + }) + .finally(() => { + d._loading = false; + }); + } else { + d._loading = false; + } }); - callback({ - data: res.data, - total: res.head.totalCount - }); + total.value = res.head.totalCount; + callback(); } }); } + +function itemEdit(row) { + selectedRow.value = row; + selectedSVUser.value = row._user; + dialog.value = true; +} + +function submit() { + if (!selectedSVUser.value) { + return ElMessage.error('璇烽�夋嫨鐢ㄦ埛'); + } + nightConstructionApi + .updateRecord({ + recordId: selectedRow.value.ncId, + userId: selectedSVUser.value.guid, + sceneId: selectedSVUser.value.dguid + }) + .then((res) => { + if (res.success) { + selectedRow.value.ncUserId = res.data.ncUserId; + selectedRow.value.ncSceneId = res.data.ncSceneId; + userApi + .getUserById(selectedRow.value.ncUserId) + .then((res1) => { + selectedRow.value._user = res1; + }) + .finally(() => { + selectedRow.value._loading = false; + }); + } + }) + .finally(() => { + dialog.value = false; + selectedRow.value._user = selectedSVUser.value; + }); +} </script> diff --git a/src/views/fysp/support/JingAnSupport.vue b/src/views/fysp/support/JingAnSupport.vue index 60016aa..b3305ee 100644 --- a/src/views/fysp/support/JingAnSupport.vue +++ b/src/views/fysp/support/JingAnSupport.vue @@ -1,5 +1,5 @@ <template> - <el-tabs type="border-card"> + <el-tabs ref="tabsRef"> <el-tab-pane label="闈欏畨澶滈棿鏂藉伐绠$悊"> <JingAnNightConstruction></JingAnNightConstruction> </el-tab-pane> @@ -12,8 +12,52 @@ </el-tabs> </template> <script setup> +import { ref, onMounted, provide, computed } from 'vue'; import NewDevice from './NewDevice.vue'; import NewConstruction from './NewConstruction.vue'; import JingAnNightConstruction from './JingAnNightConstruction.vue'; + +// 瀹氫箟 tabs ref +const tabsRef = ref(null); +const tabsHeaderHeight = ref(0); + +onMounted(() => { + // 纭繚 DOM 宸茬粡娓叉煋瀹屾垚 + setTimeout(() => { + tabsHeaderHeight.value = getTabsHeaderHeight(); + }, 0); +}); + +function getTabsHeaderHeight() { + if (tabsRef.value) { + // 鑾峰彇 el-tabs 缁勪欢鐨� DOM 鍏冪礌 + const tabsElement = tabsRef.value.$el; + + // Element UI 鐨� el-tabs header 閫氬父鏈� .el-tabs__header 绫诲悕 + const headerElement = tabsElement.querySelector('.el-tabs__header'); + + if (headerElement) { + // 鑾峰彇 header 鐨� offsetHeight锛堝寘鍚� padding 鍜� border锛屼笉鍖呭惈 margin锛� + const offsetHeight = headerElement.offsetHeight; + + // 鑾峰彇璁$畻鏍峰紡浠ヨ幏鍙� margin 鍊� + const computedStyle = window.getComputedStyle(headerElement); + + // 瑙f瀽 margin 鍊硷紙涓婁笅宸﹀彸锛� + const marginTop = parseFloat(computedStyle.marginTop || 0); + const marginBottom = parseFloat(computedStyle.marginBottom || 0); + // const marginLeft = parseFloat(computedStyle.marginLeft || 0); + // const marginRight = parseFloat(computedStyle.marginRight || 0); + + // 璁$畻鎬婚珮搴︼紙鍖呭惈鎵�鏈� padding銆乥order 鍜� margin锛� + const totalHeightWithMargin = offsetHeight + marginTop + marginBottom; + + return totalHeightWithMargin; + } + } + return 0; +} + +provide('tabsHeaderHeight', computed(() => tabsHeaderHeight.value)); </script> <style scoped></style> -- Gitblit v1.9.3