Commit 485941f703dd068a5d7faf80f1de596274648d5e

Authored by 史婷婷
1 parent f96cd580

feat: 规格变更单-列表&筛选

  1 +import request from '@/utils/request'
  2 +import { ContentTypeEnum } from '@/utils/httpEnum';
  3 +
  4 +const baseUrl = '/order/change';
  5 +
  6 +// 查询列表
  7 +export function queryApi(params) {
  8 + return request({
  9 + url: `${baseUrl}/query`,
  10 + method: 'get',
  11 + params
  12 + })
  13 +}
  14 +
  15 +// 根据ID查询详情数据
  16 +export function getDetailApi(id) {
  17 + return request({
  18 + url: `${baseUrl}`,
  19 + method: 'get',
  20 + params: { id }
  21 + })
  22 +}
  23 +
  24 +// 新增保存
  25 +export function createApi(params) {
  26 + return request({
  27 + url: `${baseUrl}`,
  28 + method: 'post',
  29 + data: params,
  30 + contentType: ContentTypeEnum.JSON
  31 + })
  32 +}
  33 +
  34 +// 修改保存
  35 +export function updateApi(params) {
  36 + return request({
  37 + url: `${baseUrl}`,
  38 + method: 'put',
  39 + data: params,
  40 + contentType: ContentTypeEnum.JSON
  41 + })
  42 +}
  43 +
  44 +// 取消
  45 +export function cancelApi(id) {
  46 + return request({
  47 + url: `${baseUrl}/cancel`,
  48 + method: 'get',
  49 + params: {
  50 + id,
  51 + status: 'CANCEL',
  52 + },
  53 + contentType: ContentTypeEnum.FORM_URLENCODED
  54 + })
  55 +}
  56 +
  57 +
  58 +// 确认变更
  59 +export function confirmApi(id) {
  60 + return request({
  61 + url: `${baseUrl}/confirm`,
  62 + method: 'get',
  63 + params: {
  64 + id,
  65 + },
  66 + contentType: ContentTypeEnum.FORM_URLENCODED
  67 + })
  68 +}
... ...
... ... @@ -174,6 +174,14 @@
174 174 }
175 175 },
176 176 {
  177 + "path": "pages/change_list/index",
  178 + "style": {
  179 + "navigationBarTitleText": "规格变更单",
  180 + "navigationBarBackgroundColor": "#ffffff",
  181 + "navigationBarTextStyle": "black"
  182 + }
  183 + },
  184 + {
177 185 "path": "pages/contract_framework/index",
178 186 "style": {
179 187 "navigationBarTitleText": "框架合同",
... ...
  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/add_icon.png" @click="onAdd" />
  9 + <image class="tool-icon" src="/static/images/dev_manage/filter_icon.png" @click="openFilter" />
  10 + </view>
  11 + </view>
  12 +
  13 + <view class="list-box">
  14 + <CardList ref="cardRef" :fetchFn="fetchList" :query="query" :extra="extraParams" :enable-refresh="true"
  15 + :enable-load-more="true" row-key="id" @loaded="onLoaded" @error="onError">
  16 + <template v-slot="{ item }">
  17 + <view class="card">
  18 + <view class="card-header">
  19 + <text class="title omit2">{{ item.orderingUnitName }}</text>
  20 + <text v-if="item.examineStatus" :class="['status', `status_${item.examineStatus}`]">{{ filterStatus(item.examineStatus)
  21 + }}</text>
  22 + </view>
  23 + <view class="info-row"><text>订单编号</text><text>{{ item.orderNo }}</text></view>
  24 + <view class="info-row"><text>生产厂</text><text>{{ item.workshopName }}</text></view>
  25 + <view class="info-row"><text>办事处</text><text>{{ item.deptName }}</text></view>
  26 + <view class="info-row"><text>变更日期</text><text>{{ item.createDate }}</text></view>
  27 + </view>
  28 + </template>
  29 + </CardList>
  30 + </view>
  31 +
  32 + <filter-modal :visible.sync="filterVisible" :value.sync="filterForm" title="筛选" @reset="onFilterReset"
  33 + @confirm="onFilterConfirm">
  34 + <template v-slot="{ model }">
  35 + <view class="filter-form">
  36 +
  37 + <view class="form-item">
  38 + <view class="label">状态</view>
  39 + <uni-data-checkbox mode="tag" :multiple="false" :value-field="'value'" :text-field="'text'"
  40 + v-model="model.examineStatus" @change="onStatusChange" :localdata="statusOptions" />
  41 + </view>
  42 +
  43 + <view class="form-item">
  44 + <view class="label">订货日期</view>
  45 + <uni-datetime-picker type="daterange" v-model="model.dateRange" start="2023-01-01" />
  46 + </view>
  47 + </view>
  48 + </template>
  49 + </filter-modal>
  50 +
  51 + </view>
  52 +</template>
  53 +
  54 +<script>
  55 +import CardList from '@/components/card/index.vue'
  56 +import FilterModal from '@/components/filter/index.vue'
  57 +import { queryApi as changeQueryApi } from '@/api/change_list.js'
  58 +import { getDicByCodeApi } from '@/api/base.js'
  59 +
  60 +export default {
  61 + name: 'ChangeList',
  62 + components: { CardList, FilterModal },
  63 + data() {
  64 + return {
  65 + searchKeyword: '',
  66 + searchKeywordDebounced: '',
  67 + searchDebounceTimer: null,
  68 + filterVisible: false,
  69 + filterForm: {
  70 + examineStatus: '',
  71 + dateRange: []
  72 + },
  73 + statusOptions: [],
  74 + query: {},
  75 + extraParams: {},
  76 + currentItems: []
  77 + }
  78 + },
  79 + created() {
  80 + this.extraParams = {}
  81 + this.loadStatusOptions()
  82 + },
  83 + onReachBottom() {
  84 + if (this.$refs && this.$refs.cardRef && this.$refs.cardRef.onLoadMore) {
  85 + this.$refs.cardRef.onLoadMore()
  86 + }
  87 + },
  88 + methods: {
  89 + async loadStatusOptions() {
  90 + try {
  91 + const res = await getDicByCodeApi('AUDIT_STATUS')
  92 + const list = res.data || []
  93 + this.statusOptions = list.map(it => ({ text: it.name || '', value: it.code || '' }))
  94 + } catch (e) {
  95 + this.statusOptions = []
  96 + }
  97 + },
  98 + onSearchInput(val) {
  99 + if (this.searchDebounceTimer) clearTimeout(this.searchDebounceTimer)
  100 + this.searchDebounceTimer = setTimeout(() => {
  101 + this.searchKeywordDebounced = this.searchKeyword
  102 + this.searchDebounceTimer = null
  103 + this.extraParams = {
  104 + searchKey: this.searchKeywordDebounced || '',
  105 + }
  106 + }, 800)
  107 + },
  108 + onSearchConfirm(e) {
  109 + const val = e && e.value != null ? e.value : this.searchKeyword
  110 + this.searchKeyword = val
  111 + this.searchKeywordDebounced = val
  112 + this.extraParams = {
  113 + searchKey: this.searchKeywordDebounced || '',
  114 + }
  115 + },
  116 + openFilter() { this.filterVisible = true },
  117 + onFilterReset(payload) { this.filterForm = payload },
  118 + onFilterConfirm(payload) {
  119 + // 兜底不同端 v-model 差异
  120 + if ((payload.examineStatus === '' || payload.examineStatus == null) && this.filterForm.examineStatus !== '') {
  121 + payload.examineStatus = this.filterForm.examineStatus
  122 + }
  123 + this.filterForm = payload
  124 + // 将条件同步给 CardList
  125 + const query = { ...payload }
  126 + // 处理日期范围 -> 拆分到 orderDateStart/orderDateEnd
  127 + if (Array.isArray(query.dateRange) && query.dateRange.length === 2) {
  128 + query.orderDateStart = query.dateRange[0]
  129 + query.orderDateEnd = query.dateRange[1]
  130 + delete query.dateRange
  131 + }
  132 + this.query = query
  133 + this.filterVisible = false
  134 + },
  135 + onStatusChange(e) {
  136 + const raw = e && e.detail && e.detail.value !== undefined ? e.detail.value : (e && e.value !== undefined ? e.value : '')
  137 + this.filterForm.examineStatus = raw
  138 + },
  139 + onLoaded({ items }) { this.currentItems = items || [] },
  140 + onError() { uni.showToast({ title: '列表加载失败', icon: 'none' }) },
  141 + fetchList({ pageIndex, pageSize, query, extra }) {
  142 + const params = { pageIndex, pageSize, ...query, ...extra }
  143 + return changeQueryApi(params).then(res => {
  144 + const _data = res && res.data ? res.data : {}
  145 + let records = _data.datas || _data.list || _data.records || []
  146 + const totalCount = _data.totalCount || _data.count || 0
  147 + const hasNext = _data.hasNext || false
  148 + const statusTextMap = (this.statusOptions || []).reduce((acc, it) => {
  149 + acc[String(it.value)] = it.text
  150 + return acc
  151 + }, {})
  152 + records = records.map(it => ({
  153 + ...it,
  154 + statusName: statusTextMap[String(it.examineStatus)] || ''
  155 + }))
  156 + return { records, totalCount, hasNext }
  157 + }).catch(() => {
  158 + this.onError()
  159 + return { records: [], totalCount: 0, hasNext: false }
  160 + })
  161 + },
  162 + filterStatus(status) {
  163 + return this.statusOptions.filter(item => item.value === status)[0].text || '';
  164 + },
  165 + onAdd() {
  166 + uni.navigateTo({
  167 + url: '/pages/change_list/add'
  168 + })
  169 + },
  170 + }
  171 +}
  172 +</script>
  173 +
  174 +<style lang="scss" scoped>
  175 +.page {
  176 + display: flex;
  177 + flex-direction: column;
  178 + height: 100vh;
  179 +}
  180 +
  181 +.fixed {
  182 + position: fixed;
  183 + top: 96rpx;
  184 + left: 0;
  185 + right: 0;
  186 + z-index: 2;
  187 + background: #fff;
  188 +}
  189 +
  190 +.search-row {
  191 + display: flex;
  192 + align-items: center;
  193 + padding: 16rpx 32rpx;
  194 +}
  195 +
  196 +.search-row .tool-icon {
  197 + width: 48rpx;
  198 + height: 48rpx;
  199 + margin-left: 16rpx;
  200 +}
  201 +
  202 +.search-row .uni-searchbar {
  203 + padding: 0;
  204 + flex: 1;
  205 +}
  206 +
  207 +::v-deep .uni-searchbar__box {
  208 + height: 80rpx !important;
  209 + justify-content: start;
  210 +}
  211 +
  212 +::v-deep .uni-searchbar__box .uni-searchbar__box-search-input {
  213 + font-size: 32rpx !important;
  214 +}
  215 +
  216 +.list-box {
  217 + flex: 1;
  218 + padding: 120rpx 0 0;
  219 +}
  220 +
  221 +.card {
  222 + position: relative;
  223 +
  224 + .card-header {
  225 + margin-bottom: 28rpx;
  226 + position: relative;
  227 +
  228 + .title {
  229 + font-size: 36rpx;
  230 + font-weight: 600;
  231 + line-height: 50rpx;
  232 + color: rgba(0, 0, 0, 0.9);
  233 + width: 578rpx;
  234 + }
  235 +
  236 + .status {
  237 + font-weight: 600;
  238 + position: absolute;
  239 + top: -32rpx;
  240 + right: -32rpx;
  241 + height: 48rpx;
  242 + line-height: 48rpx;
  243 + color: #fff;
  244 + font-size: 24rpx;
  245 + padding: 0 14rpx;
  246 + border-radius: 6rpx;
  247 +
  248 + // 审核中
  249 + &.status_AUDIT {
  250 + background: $theme-primary;
  251 + }
  252 +
  253 + // 审核通过
  254 + &.status_PASS {
  255 + background: #2BA471;
  256 + }
  257 +
  258 + // 已驳回
  259 + &.status_REFUSE {
  260 + background: #d54941;
  261 + }
  262 +
  263 + // 已取消
  264 + &.status_CANCEL {
  265 + background: #e7e7e7;
  266 + color: rgba(0, 0, 0, 0.6);
  267 + }
  268 +
  269 + }
  270 + }
  271 +
  272 + .info-row {
  273 + display: flex;
  274 + align-items: center;
  275 + color: rgba(0, 0, 0, 0.6);
  276 + font-size: 28rpx;
  277 + margin-bottom: 24rpx;
  278 +
  279 + &:last-child {
  280 + margin-bottom: 0;
  281 + }
  282 +
  283 + text {
  284 + width: 60%;
  285 + line-height: 32rpx;
  286 +
  287 + &:last-child {
  288 + color: rgba(0, 0, 0, 0.9);
  289 + width: 40%;
  290 + }
  291 + }
  292 + }
  293 +
  294 +}
  295 +
  296 +.filter-form {
  297 + .form-item {
  298 + margin-bottom: 24rpx;
  299 + }
  300 +
  301 + .label {
  302 + margin-bottom: 20rpx;
  303 + color: rgba(0, 0, 0, 0.9);
  304 + height: 44rpx;
  305 + line-height: 44rpx;
  306 + font-size: 30rpx;
  307 + }
  308 +}
  309 +
  310 +/* 深度覆盖 uni-data-checkbox(mode=tag)内部的 tag 展示与间距 */
  311 +::v-deep .filter-form .uni-data-checklist .checklist-group {
  312 + .checklist-box {
  313 + &.is--tag {
  314 + width: 212rpx;
  315 + margin-top: 0;
  316 + margin-bottom: 24rpx;
  317 + margin-right: 24rpx;
  318 + height: 80rpx;
  319 + padding: 0;
  320 + border-radius: 12rpx;
  321 + background-color: #f3f3f3;
  322 + border-color: #f3f3f3;
  323 +
  324 + &:nth-child(3n) {
  325 + margin-right: 0;
  326 + }
  327 +
  328 + .checklist-content {
  329 + display: flex;
  330 + justify-content: center;
  331 + }
  332 +
  333 + .checklist-text {
  334 + color: rgba(0, 0, 0, 0.9);
  335 + font-size: 28rpx;
  336 + }
  337 + }
  338 +
  339 + &.is-checked {
  340 + background-color: $theme-primary-plain-bg !important;
  341 + border-color: $theme-primary-plain-bg !important;
  342 +
  343 + .checklist-text {
  344 + color: $theme-primary !important;
  345 + }
  346 + }
  347 + }
  348 +
  349 +}
  350 +</style>
... ...
... ... @@ -164,7 +164,7 @@ export default {
164 164 },
165 165 onAdd() {
166 166 uni.navigateTo({
167   - url: '/pages/order_revoke/add'
  167 + url: '/pages/revoke_list/add'
168 168 })
169 169 },
170 170 }
... ...