Commit 6e7e5d4b1e41acd60713440fbeef6334f2d3c446

Authored by 史婷婷
1 parent a0781077

feat: 流程中心-我的发起-列表&筛选 + 筛选组件优化

  1 +import request from '@/utils/request'
  2 +
  3 +
  4 +// 查询列表
  5 +export function queryApi(params) {
  6 + return request({
  7 + url: `/flow/task/list/my`,
  8 + method: 'get',
  9 + params
  10 + })
  11 +}
\ No newline at end of file
... ...
... ... @@ -89,7 +89,6 @@ export default {
89 89 .filter-modal {
90 90 width: 100%;
91 91 max-height: 70vh;
92   - min-height: 40vh;
93 92 background: #fff;
94 93 border-radius: 20rpx 20rpx 0 0;
95 94 overflow: hidden;
... ...
... ... @@ -84,6 +84,14 @@
84 84 }
85 85 },
86 86 {
  87 + "path": "pages/flow/myflow",
  88 + "style": {
  89 + "navigationBarTitleText": "我发起的",
  90 + "navigationBarBackgroundColor": "#ffffff",
  91 + "navigationBarTextStyle": "black"
  92 + }
  93 + },
  94 + {
87 95 "path": "pages/contract_framework/index",
88 96 "style": {
89 97 "navigationBarTitleText": "框架合同",
... ...
... ... @@ -123,10 +123,6 @@
123 123 getTodoTypeStatisticsApi,
124 124 batchApproveApi
125 125 } from '@/api/devManage.js'
126   - import {
127   - getDicByCodes,
128   - getDicName
129   - } from '@/utils/dic';
130 126
131 127 export default {
132 128 components: {
... ...
  1 +<template>
  2 + <view class="page">
  3 + <view class="fixed">
  4 + <view class="search-row">
  5 + <uni-search-bar v-model="searchKeyword" radius="6" placeholder="请输入流程编号/名称/标题" clearButton="auto"
  6 + cancelButton="none" bgColor="#F3F3F3" textColor="rgba(0,0,0,0.4)" @confirm="onSearchConfirm"
  7 + @input="onSearchInput" />
  8 + <image class="tool-icon" src="/static/images/dev_manage/filter_icon.png" @click="openFilter" />
  9 + </view>
  10 + </view>
  11 +
  12 + <view class="list-box">
  13 + <CardList ref="cardRef" :fetchFn="fetchList" :query="query" :extra="extra" :enable-refresh="true"
  14 + :enable-load-more="true" row-key="id" @loaded="onLoaded" @error="onError">
  15 + <template v-slot="{ item }">
  16 + <view class="card">
  17 + <view class="card-header">
  18 + <text class="title omit2">{{ item.title }}</text>
  19 + </view>
  20 + <view class="info-row">
  21 + <text>流程模块</text><text>{{ getDicName('PROCESS_MODE', item.mode, cardModeOptions) }}</text>
  22 + </view>
  23 + <view class="info-row">
  24 + <text>发起人</text><text>{{ item.startBy }}</text>
  25 + </view>
  26 + <view class="info-row">
  27 + <text>发起时间</text><text>{{ item.startTime }}</text>
  28 + </view>
  29 + <view class="footer">
  30 + <button class="btn" type="primary" plain @click.stop="onDetail(item)">审核详情</button>
  31 + </view>
  32 + </view>
  33 + </template>
  34 + </CardList>
  35 + </view>
  36 +
  37 + <filter-modal :visible.sync="filterVisible" :value.sync="filterForm" title="筛选" @reset="onFilterReset"
  38 + @confirm="onFilterConfirm">
  39 + <template v-slot="{ model }">
  40 + <view class="filter-form">
  41 + <view class="form-item">
  42 + <view class="label">流程模块</view>
  43 + <view class="fake-select" @click="openModeSelect">
  44 + <text v-if="!model.mode" class="placeholder">请选择</text>
  45 + <text v-else class="value">{{ model.modeName }}</text>
  46 + </view>
  47 + </view>
  48 + </view>
  49 + </template>
  50 + </filter-modal>
  51 +
  52 + <SingleSelectSheet :visible.sync="modeSelectVisible" :options="modeOptions" v-model="filterForm.mode"
  53 + title="流程模块" @confirm="onModeConfirm" />
  54 + </view>
  55 +</template>
  56 +
  57 +<script>
  58 + import CardList from '@/components/card/index.vue'
  59 + import FilterModal from '@/components/filter/index.vue'
  60 + import SingleSelectSheet from '@/components/single-select/index.vue'
  61 + import {
  62 + queryApi
  63 + } from '@/api/flow.js'
  64 + import {
  65 + getDicByCodes
  66 + } from '@/utils/dic'
  67 + import {
  68 + getDicName
  69 + } from '@/utils/dic.js'
  70 +
  71 + export default {
  72 + name: 'MyFlow',
  73 + components: {
  74 + CardList,
  75 + FilterModal,
  76 + SingleSelectSheet
  77 + },
  78 + data() {
  79 + return {
  80 + searchKeyword: '',
  81 + searchKeywordDebounced: '',
  82 + searchDebounceTimer: null,
  83 + filterVisible: false,
  84 + filterForm: {
  85 + mode: '',
  86 + modeName: ''
  87 + },
  88 + modeSelectVisible: false,
  89 + modeOptions: [],
  90 + cardModeOptions: [],
  91 + query: {},
  92 + extra: {},
  93 + currentItems: []
  94 + }
  95 + },
  96 + created() {
  97 + this.loadModeOptions()
  98 + },
  99 + onReachBottom() {
  100 + if (this.$refs && this.$refs.cardRef && this.$refs.cardRef.onLoadMore) {
  101 + this.$refs.cardRef.onLoadMore()
  102 + }
  103 + },
  104 + watch: {},
  105 + methods: {
  106 + onSearchInput(val) {
  107 + if (this.searchDebounceTimer) clearTimeout(this.searchDebounceTimer)
  108 + this.searchDebounceTimer = setTimeout(() => {
  109 + this.searchKeywordDebounced = this.searchKeyword
  110 + this.searchDebounceTimer = null
  111 + this.extra = {
  112 + searchKey: this.searchKeywordDebounced || '',
  113 + mode: this.filterForm.mode || ''
  114 + }
  115 + }, 800)
  116 + },
  117 + onSearchConfirm(e) {
  118 + const val = e && e.value != null ? e.value : this.searchKeyword
  119 + this.searchKeyword = val
  120 + this.searchKeywordDebounced = val
  121 + this.extra = {
  122 + searchKey: this.searchKeywordDebounced || '',
  123 + mode: this.filterForm.mode || ''
  124 + }
  125 + },
  126 + openFilter() {
  127 + this.filterVisible = true
  128 + },
  129 + onFilterReset(payload) {
  130 + this.filterForm = payload
  131 + },
  132 + onFilterConfirm(payload) {
  133 + // 兜底:部分端可能未同步 v-model
  134 + if ((payload.mode === '' || payload.mode == null) && this.filterForm.mode !== '') {
  135 + payload.mode = this.filterForm.mode
  136 + payload.modeName = this.filterForm.modeName
  137 + }
  138 + this.filterForm = payload
  139 + // 仅在确认时更新给 CardList 的条件
  140 + this.extra = {
  141 + searchKey: this.searchKeywordDebounced || '',
  142 + mode: payload.mode || ''
  143 + }
  144 + this.filterVisible = false
  145 + },
  146 + openModeSelect() {
  147 + this.modeSelectVisible = true
  148 + },
  149 + onModeConfirm({
  150 + value,
  151 + label
  152 + }) {
  153 + this.filterForm.mode = value || '';
  154 + this.filterForm.modeName = label || '';
  155 + },
  156 + onLoaded({
  157 + items
  158 + }) {
  159 + this.currentItems = items || []
  160 + },
  161 + onError() {
  162 + uni.showToast({
  163 + title: '列表加载失败',
  164 + icon: 'none'
  165 + })
  166 + },
  167 + async loadModeOptions() {
  168 + try {
  169 + const dicCodes = ['PROCESS_MODE']
  170 + const results = await getDicByCodes(dicCodes)
  171 + const option = results.PROCESS_MODE.data || []
  172 + this.cardModeOptions = Array.isArray(option) ? option : [];
  173 + this.modeOptions = option.map(it => ({
  174 + label: it.name || '',
  175 + value: it.code || ''
  176 + }))
  177 + } catch (e) {
  178 + this.modeOptions = [];
  179 + this.cardModeOptions = [];
  180 + }
  181 + },
  182 + fetchList({
  183 + pageIndex,
  184 + pageSize,
  185 + query,
  186 + extra
  187 + }) {
  188 + const params = {
  189 + pageIndex,
  190 + pageSize,
  191 + ...query,
  192 + ...extra
  193 + }
  194 + return queryApi(params).then(res => {
  195 + const _data = res.data || {}
  196 + const records = _data.datas || _data.list || _data.records || []
  197 + const totalCount = _data.totalCount || _data.count || 0
  198 + const hasNext = _data.hasNext || false
  199 + return {
  200 + records,
  201 + totalCount,
  202 + hasNext
  203 + }
  204 + }).catch(() => {
  205 + this.onError()
  206 + return {
  207 + records: [],
  208 + totalCount: 0,
  209 + hasNext: false
  210 + }
  211 + })
  212 + },
  213 + onDetail(item) {
  214 + uni.showToast({
  215 + title: '审核详情',
  216 + icon: 'none'
  217 + })
  218 + },
  219 + getDicName: getDicName,
  220 + }
  221 + }
  222 +</script>
  223 +
  224 +<style lang="scss" scoped>
  225 + .page {
  226 + display: flex;
  227 + flex-direction: column;
  228 + height: 100vh;
  229 + }
  230 +
  231 + .fixed {
  232 + position: fixed;
  233 + top: 96rpx;
  234 + left: 0;
  235 + right: 0;
  236 + z-index: 2;
  237 + background: #fff;
  238 + }
  239 +
  240 + .search-row {
  241 + display: flex;
  242 + align-items: center;
  243 + padding: 16rpx 32rpx;
  244 +
  245 + .tool-icon {
  246 + width: 48rpx;
  247 + height: 48rpx;
  248 + margin-left: 16rpx;
  249 + }
  250 +
  251 + .uni-searchbar {
  252 + padding: 0;
  253 + flex: 1;
  254 + }
  255 + }
  256 +
  257 + /* 仅当前页覆盖 uni-search-bar 盒子高度 */
  258 + ::v-deep .uni-searchbar__box {
  259 + height: 80rpx !important;
  260 + justify-content: start;
  261 +
  262 + .uni-searchbar__box-search-input {
  263 + font-size: 32rpx !important;
  264 + }
  265 + }
  266 +
  267 + .list-box {
  268 + flex: 1;
  269 + padding: 112rpx 0 0
  270 + }
  271 +
  272 + .card {
  273 + .footer {
  274 + margin-top: 28rpx;
  275 + box-shadow: inset 0px 1px 0px 0px #E7E7E7;
  276 + padding-top: 22rpx;
  277 + display: flex;
  278 + justify-content: flex-end;
  279 + .btn {
  280 + height: 64rpx;
  281 + line-height: 60rpx;
  282 + font-size: 28rpx;
  283 + width: 160rpx;
  284 + margin-left: auto;
  285 + margin-right: 0;
  286 + }
  287 + }
  288 +
  289 + .card-header {
  290 + margin-bottom: 28rpx;
  291 +
  292 + .title {
  293 + font-size: 36rpx;
  294 + font-weight: 600;
  295 + line-height: 50rpx;
  296 + color: #323241;
  297 + }
  298 + }
  299 +
  300 + .info-row {
  301 + display: flex;
  302 + align-items: center;
  303 + color: rgba(0, 0, 0, 0.6);
  304 + font-size: 28rpx;
  305 + margin-bottom: 24rpx;
  306 + height: 32rpx;
  307 +
  308 + &:last-child {
  309 + margin-bottom: 0;
  310 + }
  311 +
  312 + text {
  313 + width: 60%;
  314 +
  315 + &:last-child {
  316 + color: rgba(0, 0, 0, 0.9);
  317 + width: 40%;
  318 + }
  319 + }
  320 + }
  321 + }
  322 +
  323 + .filter-form {
  324 + .form-item {
  325 + margin-bottom: 24rpx;
  326 + }
  327 +
  328 + .label {
  329 + margin-bottom: 20rpx;
  330 + color: rgba(0, 0, 0, 0.9);
  331 + height: 44rpx;
  332 + line-height: 44rpx;
  333 + font-size: 30rpx;
  334 + }
  335 +
  336 + .fake-select {
  337 + height: 80rpx;
  338 + line-height: 80rpx;
  339 + padding: 0 20rpx;
  340 + background: #f3f3f3;
  341 + border-radius: 12rpx;
  342 +
  343 + .placeholder {
  344 + color: #999;
  345 + }
  346 +
  347 + .value {
  348 + color: #333;
  349 + }
  350 + }
  351 + }
  352 +</style>
\ No newline at end of file
... ...
... ... @@ -21,7 +21,7 @@
21 21 <text class="card-num">24</text>
22 22 </view>
23 23 </view>
24   - <view class="stat-card" @click="navigateTo('/pages/myflow/index')">
  24 + <view class="stat-card" @click="navigateTo('/pages/flow/myflow')">
25 25 <image class="card-bg" src="/static/images/index/card_launch.png" mode="aspectFill" />
26 26 <view class="card-content">
27 27 <text class="card-title">我发起的</text>
... ...