|
@@ -5,7 +5,6 @@
|
|
|
<header class="mp-wv-header">
|
|
<header class="mp-wv-header">
|
|
|
<div class="mp-wv-header__row">
|
|
<div class="mp-wv-header__row">
|
|
|
<button class="mp-wv-header__back" type="button" @click="goBack">← 工作台</button>
|
|
<button class="mp-wv-header__back" type="button" @click="goBack">← 工作台</button>
|
|
|
- <button class="mp-wv-btn mp-wv-btn--primary" type="button" @click="goNew">新增</button>
|
|
|
|
|
</div>
|
|
</div>
|
|
|
<h1>运输计划</h1>
|
|
<h1>运输计划</h1>
|
|
|
<input
|
|
<input
|
|
@@ -17,61 +16,135 @@
|
|
|
/>
|
|
/>
|
|
|
</header>
|
|
</header>
|
|
|
|
|
|
|
|
- <div class="mp-wv-chips">
|
|
|
|
|
- <button
|
|
|
|
|
- v-for="item in dateChips"
|
|
|
|
|
- :key="item.value"
|
|
|
|
|
- type="button"
|
|
|
|
|
- class="mp-wv-chip"
|
|
|
|
|
- :class="{ 'is-active': dateShortcut === item.value }"
|
|
|
|
|
- @click="applyDate(item.value)"
|
|
|
|
|
- >
|
|
|
|
|
- {{ item.label }}
|
|
|
|
|
- </button>
|
|
|
|
|
|
|
+ <div class="mp-wv-filter-wrap">
|
|
|
|
|
+ <div class="mp-wv-filter-bar">
|
|
|
|
|
+ <button
|
|
|
|
|
+ class="mp-wv-filter-trig"
|
|
|
|
|
+ :class="{ open: openFilter === 'date' }"
|
|
|
|
|
+ type="button"
|
|
|
|
|
+ @click="toggleFilter('date')"
|
|
|
|
|
+ >
|
|
|
|
|
+ <span>{{ dateLabel }}</span>
|
|
|
|
|
+ <span>▼</span>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ <button
|
|
|
|
|
+ class="mp-wv-filter-trig"
|
|
|
|
|
+ :class="{ open: openFilter === 'tab' }"
|
|
|
|
|
+ type="button"
|
|
|
|
|
+ @click="toggleFilter('tab')"
|
|
|
|
|
+ >
|
|
|
|
|
+ <span>{{ tabLabel }}</span>
|
|
|
|
|
+ <span>▼</span>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="mp-wv-filter-panel" :class="{ open: openFilter === 'date' }">
|
|
|
|
|
+ <button
|
|
|
|
|
+ v-for="item in dateOptions"
|
|
|
|
|
+ :key="item.value"
|
|
|
|
|
+ class="mp-wv-filter-opt"
|
|
|
|
|
+ :class="{ active: dateShortcut === item.value }"
|
|
|
|
|
+ type="button"
|
|
|
|
|
+ @click="pickDate(item.value)"
|
|
|
|
|
+ >
|
|
|
|
|
+ <span>{{ item.label }}</span>
|
|
|
|
|
+ <span v-if="dateShortcut === item.value">✓</span>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ <div v-if="dateShortcut === 'custom'" class="mp-wv-custom-date">
|
|
|
|
|
+ <div class="mp-wv-custom-date__row">
|
|
|
|
|
+ <input v-model="customFrom" class="mp-wv-custom-date__input" type="date" />
|
|
|
|
|
+ <input v-model="customTo" class="mp-wv-custom-date__input" type="date" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <button class="mp-wv-btn mp-wv-btn--primary" type="button" style="width: 100%" @click="applyCustomDate">
|
|
|
|
|
+ 确定
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="mp-wv-filter-panel" :class="{ open: openFilter === 'tab' }">
|
|
|
|
|
+ <button
|
|
|
|
|
+ v-for="tab in PL_PLAN_LIST_TABS"
|
|
|
|
|
+ :key="tab.name"
|
|
|
|
|
+ class="mp-wv-filter-opt"
|
|
|
|
|
+ :class="{ active: activeTab === tab.name }"
|
|
|
|
|
+ type="button"
|
|
|
|
|
+ @click="pickTab(tab.name)"
|
|
|
|
|
+ >
|
|
|
|
|
+ <span>{{ tab.label }}</span>
|
|
|
|
|
+ <span v-if="activeTab === tab.name">✓</span>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ <div
|
|
|
|
|
+ class="mp-wv-filter-mask"
|
|
|
|
|
+ :class="{ open: !!openFilter }"
|
|
|
|
|
+ @click="closeFilter"
|
|
|
|
|
+ />
|
|
|
|
|
|
|
|
- <div class="mp-wv-tabs">
|
|
|
|
|
- <button
|
|
|
|
|
- v-for="tab in PL_PLAN_LIST_TABS"
|
|
|
|
|
- :key="tab.name"
|
|
|
|
|
- type="button"
|
|
|
|
|
- class="mp-wv-tab"
|
|
|
|
|
- :class="{ 'is-active': activeTab === tab.name }"
|
|
|
|
|
- @click="applyTab(tab.name)"
|
|
|
|
|
|
|
+ <div class="mp-wv-pad-speed">
|
|
|
|
|
+ <div v-if="loading && !planRows.length" class="mp-wv-empty">加载中…</div>
|
|
|
|
|
+ <div v-else-if="!planRows.length" class="mp-wv-empty">暂无计划</div>
|
|
|
|
|
+ <article
|
|
|
|
|
+ v-for="row in planRows"
|
|
|
|
|
+ :key="row.plan.id"
|
|
|
|
|
+ class="mp-wv-card"
|
|
|
|
|
+ @click="goDetail(row.plan.id)"
|
|
|
>
|
|
>
|
|
|
- {{ tab.label }}
|
|
|
|
|
- </button>
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
+ <div class="mp-wv-card__head">
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <div class="mp-wv-card__no">{{ row.card.planNo }}</div>
|
|
|
|
|
+ <div class="mp-wv-card__sub">{{ row.card.typeLabel }} · {{ row.card.planDate }}</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <el-tag :type="row.card.statusTagType" size="small">{{ row.card.statusLabel }}</el-tag>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="mp-wv-card__meta">供方 → 需方:{{ row.card.partyLine }}</div>
|
|
|
|
|
+ <div class="mp-wv-card__meta">跟进人:{{ row.card.follower }}</div>
|
|
|
|
|
+ <div class="mp-wv-card__meta">车牌:{{ row.card.plate }}</div>
|
|
|
|
|
+ <div class="mp-wv-card__meta">人员:{{ row.card.people }}</div>
|
|
|
|
|
+ <div class="mp-wv-card__product">{{ row.card.product }}</div>
|
|
|
|
|
+ <div class="mp-wv-card-actions" @click.stop>
|
|
|
|
|
+ <button class="mp-wv-btn" type="button" @click="openCardMore(row.plan)">更多</button>
|
|
|
|
|
+ <button class="mp-wv-btn" type="button" @click="goCopy(row.plan.id)">复制</button>
|
|
|
|
|
+ <button
|
|
|
|
|
+ v-if="row.canArrange"
|
|
|
|
|
+ class="mp-wv-btn mp-wv-btn--primary"
|
|
|
|
|
+ type="button"
|
|
|
|
|
+ @click="goArrange(row.plan.id)"
|
|
|
|
|
+ >
|
|
|
|
|
+ {{ row.arrangeLabel }}
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </article>
|
|
|
|
|
|
|
|
- <div class="mp-wv-toolbar">
|
|
|
|
|
- <button class="mp-wv-btn" type="button" @click="goPaste">三方人车</button>
|
|
|
|
|
|
|
+ <div v-if="hasMore" class="mp-wv-toolbar" style="padding: 0 0 12px">
|
|
|
|
|
+ <button class="mp-wv-btn" type="button" style="width: 100%" :disabled="loading" @click="loadMore">
|
|
|
|
|
+ {{ loading ? '加载中…' : `加载更多(${plans.length}/${total})` }}
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- <div v-if="loading && !cards.length" class="mp-wv-empty">加载中…</div>
|
|
|
|
|
- <div v-else-if="!cards.length" class="mp-wv-empty">暂无计划</div>
|
|
|
|
|
- <article
|
|
|
|
|
- v-for="card in cards"
|
|
|
|
|
- :key="card.id"
|
|
|
|
|
- class="mp-wv-card"
|
|
|
|
|
- @click="goDetail(card.id)"
|
|
|
|
|
- >
|
|
|
|
|
- <div class="mp-wv-card__head">
|
|
|
|
|
- <div>
|
|
|
|
|
- <div class="mp-wv-card__no">{{ card.planNo }}</div>
|
|
|
|
|
- <div class="mp-wv-card__sub">{{ card.typeLabel }} · {{ card.planDate }}</div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <el-tag :type="card.statusTagType" size="small">{{ card.statusLabel }}</el-tag>
|
|
|
|
|
|
|
+ <div class="mp-wv-speed-mask" :class="{ open: speedOpen }" @click="speedOpen = false" />
|
|
|
|
|
+ <div class="mp-wv-speed-dial" :class="{ open: speedOpen }">
|
|
|
|
|
+ <div class="mp-wv-speed-menu">
|
|
|
|
|
+ <button class="mp-wv-speed-item" type="button" @click="goPaste">三方人车快速创建</button>
|
|
|
|
|
+ <button class="mp-wv-speed-item primary" type="button" @click="goNew">新增计划</button>
|
|
|
</div>
|
|
</div>
|
|
|
- <div class="mp-wv-card__meta">车牌:{{ card.plate }}</div>
|
|
|
|
|
- <div class="mp-wv-card__meta">人员:{{ card.people }}</div>
|
|
|
|
|
- <div class="mp-wv-card__product">{{ card.product }}</div>
|
|
|
|
|
- </article>
|
|
|
|
|
-
|
|
|
|
|
- <div v-if="hasMore" class="mp-wv-toolbar">
|
|
|
|
|
- <button class="mp-wv-btn" type="button" :disabled="loading" @click="loadMore">
|
|
|
|
|
- {{ loading ? '加载中…' : '加载更多' }}
|
|
|
|
|
|
|
+ <button class="mp-wv-speed-main" type="button" aria-label="快捷操作" @click="toggleSpeed">
|
|
|
|
|
+ +
|
|
|
</button>
|
|
</button>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+
|
|
|
|
|
+ <MpBottomSheet v-model="moreOpen" title="卡片操作" half>
|
|
|
|
|
+ <button
|
|
|
|
|
+ v-for="item in moreActions"
|
|
|
|
|
+ :key="item.key"
|
|
|
|
|
+ class="mp-wv-filter-opt"
|
|
|
|
|
+ :class="{ 'is-danger': item.danger }"
|
|
|
|
|
+ type="button"
|
|
|
|
|
+ :disabled="acting"
|
|
|
|
|
+ @click="runMoreAction(item.key)"
|
|
|
|
|
+ >
|
|
|
|
|
+ {{ item.label }}
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </MpBottomSheet>
|
|
|
</template>
|
|
</template>
|
|
|
</MpWebviewShell>
|
|
</MpWebviewShell>
|
|
|
</template>
|
|
</template>
|
|
@@ -79,7 +152,9 @@
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
import { computed, onMounted, ref } from 'vue'
|
|
import { computed, onMounted, ref } from 'vue'
|
|
|
import { useRouter } from 'vue-router'
|
|
import { useRouter } from 'vue-router'
|
|
|
|
|
+ import { ElMessage, ElMessageBox } from 'element-plus'
|
|
|
import MpWebviewShell from '@/layouts/MpWebviewShell.vue'
|
|
import MpWebviewShell from '@/layouts/MpWebviewShell.vue'
|
|
|
|
|
+ import MpBottomSheet from '@/components/mp/MpBottomSheet.vue'
|
|
|
import { planApi, type Plan } from '@/api/pl'
|
|
import { planApi, type Plan } from '@/api/pl'
|
|
|
import { buildPlanCard } from '@/utils/mp-pl-plan-card'
|
|
import { buildPlanCard } from '@/utils/mp-pl-plan-card'
|
|
|
import { getWxMiniProgram } from '@/utils/mp-webview'
|
|
import { getWxMiniProgram } from '@/utils/mp-webview'
|
|
@@ -88,17 +163,32 @@
|
|
|
plPlanListTabToFilters,
|
|
plPlanListTabToFilters,
|
|
|
type PlPlanListTab
|
|
type PlPlanListTab
|
|
|
} from '@/utils/pl-display'
|
|
} from '@/utils/pl-display'
|
|
|
|
|
+ import {
|
|
|
|
|
+ arrangeTransportLabel,
|
|
|
|
|
+ canArrangeTransport,
|
|
|
|
|
+ canCancelWaitNotice,
|
|
|
|
|
+ canVoidPlan,
|
|
|
|
|
+ canWaitNotice
|
|
|
|
|
+ } from '@/utils/pl-plan-action-guards'
|
|
|
import { HttpError } from '@/utils/http/error'
|
|
import { HttpError } from '@/utils/http/error'
|
|
|
import { ApiStatus } from '@/utils/http/status'
|
|
import { ApiStatus } from '@/utils/http/status'
|
|
|
import '@/styles/mp-webview.scss'
|
|
import '@/styles/mp-webview.scss'
|
|
|
|
|
|
|
|
- type DateChip = 'today' | 'tomorrow' | 'week' | 'month'
|
|
|
|
|
|
|
+ type DateShortcut = 'today' | 'tomorrow' | 'week' | 'month' | 'custom'
|
|
|
|
|
|
|
|
const router = useRouter()
|
|
const router = useRouter()
|
|
|
const keyword = ref('')
|
|
const keyword = ref('')
|
|
|
const activeTab = ref<PlPlanListTab>('pending_arrange')
|
|
const activeTab = ref<PlPlanListTab>('pending_arrange')
|
|
|
- const dateShortcut = ref<DateChip>('today')
|
|
|
|
|
|
|
+ const dateShortcut = ref<DateShortcut>('today')
|
|
|
const dateRange = ref<string[]>([])
|
|
const dateRange = ref<string[]>([])
|
|
|
|
|
+ const customFrom = ref('')
|
|
|
|
|
+ const customTo = ref('')
|
|
|
|
|
+ const customDateLabel = ref('')
|
|
|
|
|
+ const openFilter = ref<'' | 'date' | 'tab'>('')
|
|
|
|
|
+ const speedOpen = ref(false)
|
|
|
|
|
+ const moreOpen = ref(false)
|
|
|
|
|
+ const morePlan = ref<Plan | null>(null)
|
|
|
|
|
+ const acting = ref(false)
|
|
|
const loading = ref(false)
|
|
const loading = ref(false)
|
|
|
const forbidden = ref(false)
|
|
const forbidden = ref(false)
|
|
|
const page = ref(1)
|
|
const page = ref(1)
|
|
@@ -106,23 +196,52 @@
|
|
|
const total = ref(0)
|
|
const total = ref(0)
|
|
|
const plans = ref<Plan[]>([])
|
|
const plans = ref<Plan[]>([])
|
|
|
|
|
|
|
|
- const dateChips: { label: string; value: DateChip }[] = [
|
|
|
|
|
|
|
+ const dateOptions: { label: string; value: DateShortcut }[] = [
|
|
|
{ label: '今天', value: 'today' },
|
|
{ label: '今天', value: 'today' },
|
|
|
{ label: '明天', value: 'tomorrow' },
|
|
{ label: '明天', value: 'tomorrow' },
|
|
|
{ label: '本周', value: 'week' },
|
|
{ label: '本周', value: 'week' },
|
|
|
- { label: '本月', value: 'month' }
|
|
|
|
|
|
|
+ { label: '本月', value: 'month' },
|
|
|
|
|
+ { label: '自定义', value: 'custom' }
|
|
|
]
|
|
]
|
|
|
|
|
|
|
|
- const cards = computed(() => plans.value.map((row) => buildPlanCard(row)))
|
|
|
|
|
|
|
+ const tabLabel = computed(
|
|
|
|
|
+ () => PL_PLAN_LIST_TABS.find((t) => t.name === activeTab.value)?.label || '待安排'
|
|
|
|
|
+ )
|
|
|
|
|
+ const dateLabel = computed(() => {
|
|
|
|
|
+ if (dateShortcut.value === 'custom') return customDateLabel.value || '自定义'
|
|
|
|
|
+ return dateOptions.find((d) => d.value === dateShortcut.value)?.label || '今天'
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ const planRows = computed(() =>
|
|
|
|
|
+ plans.value.map((plan) => ({
|
|
|
|
|
+ plan,
|
|
|
|
|
+ card: buildPlanCard(plan),
|
|
|
|
|
+ canArrange: canArrangeTransport(plan),
|
|
|
|
|
+ arrangeLabel: arrangeTransportLabel(plan)
|
|
|
|
|
+ }))
|
|
|
|
|
+ )
|
|
|
const hasMore = computed(() => plans.value.length < total.value)
|
|
const hasMore = computed(() => plans.value.length < total.value)
|
|
|
|
|
|
|
|
|
|
+ const moreActions = computed(() => {
|
|
|
|
|
+ const p = morePlan.value
|
|
|
|
|
+ if (!p) return [] as { key: string; label: string; danger?: boolean }[]
|
|
|
|
|
+ const items: { key: string; label: string; danger?: boolean }[] = [
|
|
|
|
|
+ { key: 'detail', label: '查看详情' },
|
|
|
|
|
+ { key: 'copy', label: '复制' }
|
|
|
|
|
+ ]
|
|
|
|
|
+ if (canWaitNotice(p)) items.push({ key: 'wait', label: '等客户通知' })
|
|
|
|
|
+ if (canCancelWaitNotice(p)) items.push({ key: 'cancel-wait', label: '取消等通知' })
|
|
|
|
|
+ if (canVoidPlan(p)) items.push({ key: 'void', label: '作废', danger: true })
|
|
|
|
|
+ return items
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
function formatYmd(date: Date) {
|
|
function formatYmd(date: Date) {
|
|
|
const m = `${date.getMonth() + 1}`.padStart(2, '0')
|
|
const m = `${date.getMonth() + 1}`.padStart(2, '0')
|
|
|
const d = `${date.getDate()}`.padStart(2, '0')
|
|
const d = `${date.getDate()}`.padStart(2, '0')
|
|
|
return `${date.getFullYear()}-${m}-${d}`
|
|
return `${date.getFullYear()}-${m}-${d}`
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function rangeFor(type: DateChip): string[] {
|
|
|
|
|
|
|
+ function rangeFor(type: Exclude<DateShortcut, 'custom'>): string[] {
|
|
|
const today = new Date()
|
|
const today = new Date()
|
|
|
if (type === 'today') {
|
|
if (type === 'today') {
|
|
|
const d = formatYmd(today)
|
|
const d = formatYmd(today)
|
|
@@ -170,8 +289,9 @@
|
|
|
loading.value = true
|
|
loading.value = true
|
|
|
try {
|
|
try {
|
|
|
const res = await planApi.list(buildParams())
|
|
const res = await planApi.list(buildParams())
|
|
|
- const data = (res as { data?: { list?: Plan[]; total?: number }; list?: Plan[]; total?: number })
|
|
|
|
|
- .data ?? res
|
|
|
|
|
|
|
+ const data =
|
|
|
|
|
+ (res as { data?: { list?: Plan[]; total?: number }; list?: Plan[]; total?: number }).data ??
|
|
|
|
|
+ res
|
|
|
const list = (data as { list?: Plan[] }).list || []
|
|
const list = (data as { list?: Plan[] }).list || []
|
|
|
total.value = (data as { total?: number }).total || 0
|
|
total.value = (data as { total?: number }).total || 0
|
|
|
plans.value = reset ? list : plans.value.concat(list)
|
|
plans.value = reset ? list : plans.value.concat(list)
|
|
@@ -192,14 +312,45 @@
|
|
|
void fetchPage(true)
|
|
void fetchPage(true)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function applyDate(type: DateChip) {
|
|
|
|
|
|
|
+ function closeFilter() {
|
|
|
|
|
+ openFilter.value = ''
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function toggleFilter(kind: 'date' | 'tab') {
|
|
|
|
|
+ speedOpen.value = false
|
|
|
|
|
+ openFilter.value = openFilter.value === kind ? '' : kind
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function pickDate(type: DateShortcut) {
|
|
|
dateShortcut.value = type
|
|
dateShortcut.value = type
|
|
|
|
|
+ if (type === 'custom') {
|
|
|
|
|
+ if (!customFrom.value || !customTo.value) {
|
|
|
|
|
+ const [from, to] = rangeFor('month')
|
|
|
|
|
+ customFrom.value = from
|
|
|
|
|
+ customTo.value = to
|
|
|
|
|
+ }
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
dateRange.value = rangeFor(type)
|
|
dateRange.value = rangeFor(type)
|
|
|
|
|
+ closeFilter()
|
|
|
|
|
+ reload()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function applyCustomDate() {
|
|
|
|
|
+ if (!customFrom.value || !customTo.value) {
|
|
|
|
|
+ ElMessage.warning('请选择起止日期')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ dateShortcut.value = 'custom'
|
|
|
|
|
+ dateRange.value = [customFrom.value, customTo.value]
|
|
|
|
|
+ customDateLabel.value = `${customFrom.value} ~ ${customTo.value}`
|
|
|
|
|
+ closeFilter()
|
|
|
reload()
|
|
reload()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function applyTab(tab: PlPlanListTab) {
|
|
|
|
|
|
|
+ function pickTab(tab: PlPlanListTab) {
|
|
|
activeTab.value = tab
|
|
activeTab.value = tab
|
|
|
|
|
+ closeFilter()
|
|
|
reload()
|
|
reload()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -208,6 +359,11 @@
|
|
|
void fetchPage(false)
|
|
void fetchPage(false)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ function toggleSpeed() {
|
|
|
|
|
+ closeFilter()
|
|
|
|
|
+ speedOpen.value = !speedOpen.value
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
function goBack() {
|
|
function goBack() {
|
|
|
const mini = getWxMiniProgram()
|
|
const mini = getWxMiniProgram()
|
|
|
if (mini?.navigateBack) {
|
|
if (mini?.navigateBack) {
|
|
@@ -218,10 +374,12 @@
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function goNew() {
|
|
function goNew() {
|
|
|
|
|
+ speedOpen.value = false
|
|
|
void router.push('/m/pl/plan/new')
|
|
void router.push('/m/pl/plan/new')
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function goPaste() {
|
|
function goPaste() {
|
|
|
|
|
+ speedOpen.value = false
|
|
|
void router.push('/m/pl/plan/paste')
|
|
void router.push('/m/pl/plan/paste')
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -229,8 +387,116 @@
|
|
|
void router.push(`/m/pl/plan/${id}`)
|
|
void router.push(`/m/pl/plan/${id}`)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ function goCopy(id: string) {
|
|
|
|
|
+ void router.push({ path: '/m/pl/plan/new', query: { copyFrom: id } })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function goArrange(id: string) {
|
|
|
|
|
+ void router.push(`/m/pl/plan/${id}/arrange`)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function openCardMore(plan: Plan) {
|
|
|
|
|
+ morePlan.value = plan
|
|
|
|
|
+ moreOpen.value = true
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ async function runMoreAction(key: string) {
|
|
|
|
|
+ const p = morePlan.value
|
|
|
|
|
+ if (!p) return
|
|
|
|
|
+ if (key === 'detail') {
|
|
|
|
|
+ moreOpen.value = false
|
|
|
|
|
+ goDetail(p.id)
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ if (key === 'copy') {
|
|
|
|
|
+ moreOpen.value = false
|
|
|
|
|
+ goCopy(p.id)
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ if (key === 'wait') {
|
|
|
|
|
+ await ElMessageBox.confirm('确认将该计划标记为等客户通知?', '等客户通知', {
|
|
|
|
|
+ type: 'warning'
|
|
|
|
|
+ })
|
|
|
|
|
+ acting.value = true
|
|
|
|
|
+ try {
|
|
|
|
|
+ await planApi.waitNotice(p.id)
|
|
|
|
|
+ ElMessage.success('已标记为等客户通知')
|
|
|
|
|
+ moreOpen.value = false
|
|
|
|
|
+ reload()
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ acting.value = false
|
|
|
|
|
+ }
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ if (key === 'cancel-wait') {
|
|
|
|
|
+ await ElMessageBox.confirm('确认取消等通知,恢复为待安排?', '取消等通知', {
|
|
|
|
|
+ type: 'warning'
|
|
|
|
|
+ })
|
|
|
|
|
+ acting.value = true
|
|
|
|
|
+ try {
|
|
|
|
|
+ await planApi.cancelWaitNotice(p.id)
|
|
|
|
|
+ ElMessage.success('已取消等通知')
|
|
|
|
|
+ moreOpen.value = false
|
|
|
|
|
+ reload()
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ acting.value = false
|
|
|
|
|
+ }
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ if (key === 'void') {
|
|
|
|
|
+ await ElMessageBox.confirm('确认作废该运输计划?此操作不可恢复。', '作废运输计划', {
|
|
|
|
|
+ type: 'warning'
|
|
|
|
|
+ })
|
|
|
|
|
+ acting.value = true
|
|
|
|
|
+ try {
|
|
|
|
|
+ await planApi.cancel(p.id)
|
|
|
|
|
+ ElMessage.success('已作废')
|
|
|
|
|
+ moreOpen.value = false
|
|
|
|
|
+ reload()
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ acting.value = false
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
onMounted(() => {
|
|
onMounted(() => {
|
|
|
dateRange.value = rangeFor('today')
|
|
dateRange.value = rangeFor('today')
|
|
|
reload()
|
|
reload()
|
|
|
})
|
|
})
|
|
|
</script>
|
|
</script>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped lang="scss">
|
|
|
|
|
+ .mp-wv-card-actions {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ gap: 8px;
|
|
|
|
|
+ margin-top: 10px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .mp-wv-card-actions .mp-wv-btn {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .mp-wv-custom-date {
|
|
|
|
|
+ padding: 8px 12px 12px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .mp-wv-custom-date__row {
|
|
|
|
|
+ display: grid;
|
|
|
|
|
+ grid-template-columns: 1fr 1fr;
|
|
|
|
|
+ gap: 8px;
|
|
|
|
|
+ margin-bottom: 8px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .mp-wv-custom-date__input {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 36px;
|
|
|
|
|
+ padding: 0 8px;
|
|
|
|
|
+ border: 1px solid #dcebe4;
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+ font-size: 13px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .is-danger {
|
|
|
|
|
+ color: #d14343 !important;
|
|
|
|
|
+ }
|
|
|
|
|
+</style>
|