This commit is contained in:
zlwu committed 2026-08-21 16:50:47 +08:00
1 parent 6dc8cfb2c1
commit d26fb23fcf
181 files changed
+25727 -24557

No files matched your search

+18
View File
@@ -291,6 +291,24 @@ export function fetchAllDictData() {
})
}
export function fetchEnsureDictData(data: {
dictType: string
label: string
preferredValue?: string
}) {
return request.post<{ label: string; value: string; created: boolean }>({
url: '/web/admin/dict-data/ensure',
data
})
}
export function fetchEnsureRemoveDictData(data: { dictType: string; value: string }) {
return request.post({
url: '/web/admin/dict-data/ensure-remove',
data
})
}
// ---------------------------------------------------------------------------
// 组织管理
// ---------------------------------------------------------------------------
@@ -0,0 +1,152 @@
<template>
<el-select
:model-value="modelValue"
:placeholder="placeholder"
:clearable="clearable"
:filterable="filterable"
:allow-create="allowCreate"
:default-first-option="allowCreate"
:disabled="disabled || loading"
:size="size"
:style="style"
@update:model-value="onSelect"
>
<el-option
v-for="opt in options"
:key="opt.value"
:label="opt.label"
:value="opt.value"
>
<div class="dict-select-option">
<span>{{ opt.label }}</span>
<el-button
v-if="dictStore.isSessionCreated(dictType, opt.value)"
link
type="danger"
size="small"
class="dict-select-option__remove"
@click.stop="onRemove(opt.value)"
>
<el-icon><Delete /></el-icon>
</el-button>
</div>
</el-option>
</el-select>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
import { Delete } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useDictStore } from '@/store/modules/dict'
const props = withDefaults(
defineProps<{
dictType: string
modelValue?: string | null
allowCreate?: boolean
clearable?: boolean
filterable?: boolean
disabled?: boolean
placeholder?: string
size?: '' | 'default' | 'small' | 'large'
style?: string | Record<string, string>
}>(),
{
modelValue: '',
allowCreate: true,
clearable: true,
filterable: true,
disabled: false,
placeholder: '请选择',
size: 'default'
}
)
const emit = defineEmits<{
'update:modelValue': [value: string]
change: [value: string]
}>()
const dictStore = useDictStore()
const loading = ref(false)
const options = computed(() => dictStore.getOptions(props.dictType))
function isKnown(value: string) {
return options.value.some((o) => o.value === value || o.label === value)
}
async function onSelect(raw: string | null | undefined) {
const next = raw == null ? '' : String(raw).trim()
if (!next) {
emit('update:modelValue', '')
emit('change', '')
return
}
if (!props.allowCreate || isKnown(next)) {
const known = options.value.find((o) => o.value === next || o.label === next)
const value = known?.value ?? next
emit('update:modelValue', value)
emit('change', value)
return
}
try {
await ElMessageBox.confirm(`将「${next}」新增到字典,是否继续?`, '新增字典项', {
type: 'warning',
confirmButtonText: '确定',
cancelButtonText: '取消'
})
} catch {
return
}
loading.value = true
try {
const data = await dictStore.ensure(props.dictType, next)
emit('update:modelValue', data.value)
emit('change', data.value)
} catch (e: any) {
ElMessage.error(e?.message || '写入字典失败')
} finally {
loading.value = false
}
}
async function onRemove(value: string) {
try {
await ElMessageBox.confirm(`确定从字典中删除「${value}」吗?`, '删除字典项', {
type: 'warning',
confirmButtonText: '删除',
cancelButtonText: '取消'
})
} catch {
return
}
loading.value = true
try {
await dictStore.ensureRemove(props.dictType, value)
if (props.modelValue === value) {
emit('update:modelValue', '')
emit('change', '')
}
ElMessage.success('已删除')
} catch (e: any) {
ElMessage.error(e?.message || '删除失败')
} finally {
loading.value = false
}
}
</script>
<style scoped>
.dict-select-option {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.dict-select-option__remove {
flex-shrink: 0;
}
</style>
@@ -4,7 +4,7 @@
v-model:current-page="pageModel"
v-model:page-size="limitModel"
:total="total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="LIST_PAGE_SIZES"
layout="total, sizes, prev, pager, next, jumper"
@size-change="emitPagination"
@current-change="emitPagination"
@@ -14,7 +14,7 @@
<script setup lang="ts">
import { computed } from 'vue'
import { DEFAULT_LIST_PAGE_SIZE } from '@/utils/table/tableConfig'
import { DEFAULT_LIST_PAGE_SIZE, LIST_PAGE_SIZES } from '@/utils/table/tableConfig'
const props = defineProps<{
total: number
@@ -423,7 +423,7 @@
v-model:current-page="addPagination.page"
v-model:page-size="addPagination.pageSize"
:total="addPagination.total"
:page-sizes="[10, 20, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="handleAddSizeChange"
@current-change="handleAddPageChange"
@@ -83,9 +83,20 @@
{{ row.model || row.productModel || '—' }}
</template>
</el-table-column>
<el-table-column label="单位" min-width="80" align="center">
<el-table-column label="单位" min-width="100" align="center">
<template #default="{ row }">
<DictTag dict-type="crm_product_unit" :value="row.unit" />
<DictSelect
v-if="editablePackageDelivery"
v-model="row.unit"
class="pl-plan-product-cell-control"
dict-type="crm_product_unit"
placeholder="请选择单位"
style="width: 100%"
/>
<template v-else>
<DictTag v-if="row.unit" dict-type="crm_product_unit" :value="row.unit" />
<span v-else>—</span>
</template>
</template>
</el-table-column>
<el-table-column label="计划数量" min-width="110" align="right">
@@ -126,25 +137,14 @@
</el-table-column>
<el-table-column prop="packageSpec" label="包装规格" min-width="150" align="center">
<template #default="{ row }">
<el-select
<DictSelect
v-if="editablePackageDelivery"
v-model="row.packageSpec"
class="pl-plan-product-cell-control"
dict-type="crm_product_gg"
placeholder="请选择包装规格"
filterable
allow-create
default-first-option
clearable
style="width: 100%"
@change="val => handlePackageSpecChange(row, val)"
>
<el-option
v-for="dict in dictStore.getOptions('crm_product_gg')"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
/>
<template v-else>
<DictTag v-if="row.packageSpec" dict-type="crm_product_gg" :value="row.packageSpec" />
<span v-else>—</span>
@@ -153,21 +153,14 @@
</el-table-column>
<el-table-column label="送货方式" min-width="150" align="center">
<template #default="{ row }">
<el-select
<DictSelect
v-if="editablePackageDelivery"
v-model="row.deliveryMethod"
class="pl-plan-product-cell-control"
dict-type="crm_shfs"
placeholder="请选择送货方式"
clearable
style="width: 100%"
>
<el-option
v-for="dict in dictStore.getOptions('crm_shfs')"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
/>
<template v-else>
<el-tag v-if="row.deliveryMethod" size="small" type="info">
{{ getDeliveryMethodDisplay(row.deliveryMethod) }}
@@ -236,6 +229,7 @@ import { formatBrandQtySummary } from '@/utils/pl-display'
import PlProductNameHazardCell from '@/components/business/pl-product-name-hazard-cell/index.vue'
import ProductAliasBrandDialog from '@/components/business/product-alias-brand-dialog/index.vue'
import DictTag from '@/components/DictTag/index.vue'
import DictSelect from '@/components/DictSelect/index.vue'
import { useDictStore } from '@/store/modules/dict'
const props = defineProps<{
@@ -248,7 +242,7 @@ const props = defineProps<{
editableQty?: boolean
/** 产品信息区:别名 / 品牌可改 */
editableAliasBrand?: boolean
/** 包装规格 / 送货方式可下拉编辑(对齐报价单) */
/** 单位 / 包装规格 / 送货方式可下拉编辑(对齐报价单) */
editablePackageDelivery?: boolean
/** 新增/编辑弹窗默认不展示实际数量 */
showActualQty?: boolean
@@ -269,9 +263,6 @@ const selectedProductIdSet = computed(
() => new Set((props.selectedProductIds || []).map(id => String(id)))
)
function handlePackageSpecChange(row: PlanFormProductRow, value: string | number | boolean | undefined) {
row.packageSpec = value == null || value === '' ? '' : String(value)
}
function getDeliveryMethodDisplay(method?: string) {
const label = dictStore.getLabel('crm_shfs', method || '')
@@ -80,7 +80,14 @@
</section>
<section class="pl-plan-form-section">
<h3 class="pl-plan-form-section-title">供需双方</h3>
<div class="pl-plan-form-section-head">
<h3 class="pl-plan-form-section-title">供需双方</h3>
<div class="pl-plan-form-section-actions">
<el-button class="btn-ghost" @click="handleSwapParties">
<el-icon><Sort /></el-icon>供需方互换
</el-button>
</div>
</div>
<el-form label-position="right" label-width="100px" class="pl-dialog-form">
<div class="pl-plan-party-row">
<div class="pl-plan-party-block">
@@ -377,7 +384,12 @@
</div>
<div class="pl-plan-logistics-block">
<h4 class="pl-plan-subtitle">送货信息</h4>
<div class="pl-plan-logistics-block-head">
<h4 class="pl-plan-subtitle">送货信息</h4>
<el-button text type="primary" @click="handleSwapPickupDelivery">
<el-icon><Sort /></el-icon>取送货互换
</el-button>
</div>
<div class="form-grid-2">
<el-form-item label="送货地址" class="form-col-span-2">
<PlAddressWithLibrary
@@ -472,7 +484,16 @@
</template>
<script setup lang="ts">
import { Check, Close, DocumentCopy, FolderOpened, Plus, Search, Van } from '@element-plus/icons-vue'
import {
Check,
Close,
DocumentCopy,
FolderOpened,
Plus,
Search,
Sort,
Van
} from '@element-plus/icons-vue'
import {
planApi,
transportApi,
@@ -838,6 +859,66 @@ function syncCommittedPartyIds() {
committedCustomerId.value = String(formData.customerId || '')
}
/** 供需方互换:仅交换本区字段,勿走 select change(会清空合同) */
function handleSwapParties() {
const temp = {
supplierId: formData.supplierId,
supplierName: formData.supplierName,
supplierContracts: [...formData.supplierContracts],
customerId: formData.customerId,
customerName: formData.customerName,
demanderContracts: [...formData.demanderContracts]
}
formData.supplierId = temp.customerId
formData.supplierName = temp.customerName
formData.supplierContracts = temp.demanderContracts
formData.customerId = temp.supplierId
formData.customerName = temp.supplierName
formData.demanderContracts = temp.supplierContracts
formData.destinationId = temp.supplierId
formData.destinationName = temp.supplierName
// 联系人仅绑定需方;互换后无供方联系人可对调,清空以免挂在错误客户上
formData.contactName = ''
formData.contactPhone = ''
syncCommittedPartyIds()
ElMessage.success('供需方已互换')
}
/** 取货信息 ↔ 送货信息 */
function handleSwapPickupDelivery() {
suppressAddressMutex.value = true
const temp = {
pickupAddress: formData.pickupAddress,
pickupLng: formData.pickupLng,
pickupLat: formData.pickupLat,
pickupTime: formData.pickupTime,
pickupContact: formData.pickupContact,
pickupNotes: formData.pickupNotes
}
formData.pickupAddress = formData.destinationAddress
formData.pickupLng = formData.destinationLng
formData.pickupLat = formData.destinationLat
formData.pickupTime = formData.deliveryTime
formData.pickupContact = formData.deliveryContact
formData.pickupNotes = formData.destinationNotes
formData.destinationAddress = temp.pickupAddress
formData.destinationLng = temp.pickupLng
formData.destinationLat = temp.pickupLat
formData.deliveryTime = temp.pickupTime
formData.deliveryContact = temp.pickupContact
formData.destinationNotes = temp.pickupNotes
nextTick(() => {
suppressAddressMutex.value = false
})
ElMessage.success('取送货信息已互换')
}
function handleSupplierSelectChange(customerId?: string) {
if (!customerId) {
formData.supplierId = ''
@@ -1711,6 +1792,17 @@ async function handleSubmit(mode: 'save' | 'saveAndArrange' = 'save') {
margin: 0 0 10px;
}
.pl-plan-logistics-block-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.pl-plan-logistics-block-head .pl-plan-subtitle {
margin: 0;
}
.pl-plan-party-select-row {
display: flex;
align-items: flex-start;
@@ -1838,7 +1930,11 @@ async function handleSubmit(mode: 'save' | 'saveAndArrange' = 'save') {
border-radius: 8px;
background: #f8fafc;
.pl-plan-subtitle {
> .pl-plan-subtitle {
margin: 0 0 8px;
}
.pl-plan-logistics-block-head {
margin: 0 0 8px;
}
@@ -17,7 +17,7 @@
<span class="selected-hint">已选 {{ selectedProducts.length }} 项</span>
<ListQuickSearchInput
v-model="quickSearchKeyword"
placeholder="产品名称/拼音首字母"
placeholder="产品名称/拼音首字母/规格型号"
@search="handleQuickSearch"
@clear="handleQuickSearchClear"
/>
@@ -317,6 +317,9 @@
page: queryParams.value.pageNum,
pageSize: queryParams.value.pageSize,
keyword: keyword || undefined,
// 选择器:名称/拼音/规格型号;不匹配产品编号(避免短数字误命中编号)
matchProductNo: false,
matchModel: true,
status: queryParams.value.status,
supplierId:
props.supplierId != null && props.supplierId !== '' ? String(props.supplierId) : undefined
@@ -470,7 +473,7 @@
margin-bottom: 12px;
:deep(.quick-search-input) {
width: 220px;
width: 280px;
flex-shrink: 0;
}
}
@@ -1,5 +1,6 @@
<script setup lang="ts">
import { computed } from 'vue'
import { LIST_PAGE_SIZES } from '@/utils/table/tableConfig'
import DataTablePanel from './DataTablePanel.vue'
import FilterBlock from './FilterBlock.vue'
import ListToolbar from './ListToolbar.vue'
@@ -23,7 +24,7 @@ const props = withDefaults(
tableScrollClass?: string
}>(),
{
pageSizes: () => [10, 20, 30],
pageSizes: () => [...LIST_PAGE_SIZES],
showSummary: false,
}
)
@@ -168,7 +168,7 @@
// 默认分页常量
const DEFAULT_PAGINATION_OPTIONS: PaginationOptions = {
pageSizes: [10, 20, 30, 50, 100],
pageSizes: [10, 20, 100, 500],
align: 'right',
background: true,
layout: layout.value,
@@ -122,8 +122,10 @@ export function usePlPlanArrangeActions() {
licensePlate?: string
driverUrl?: string
}) {
const lines = ['【运输安排】', `计划号:${plan.value?.planNo || '—'}`]
lines.push(`车牌:${options?.licensePlate || licensePlate.value || plan.value?.licensePlate || '—'}`)
const plate =
options?.licensePlate || licensePlate.value || plan.value?.licensePlate || '—'
const lines = [`【${plate} - 运输安排】`, `计划号:${plan.value?.planNo || '—'}`]
lines.push(`车牌:${plate}`)
lines.push(
`时间:${formatDate(plan.value?.pickupTime) || plan.value?.planDate || '—'}`
)
@@ -0,0 +1,12 @@
export const DICT_ENSURE_WHITELIST = [
'crm_product_gg',
'crm_shfs',
'crm_product_unit',
'crm_customer_park'
] as const
export type DictEnsureType = (typeof DICT_ENSURE_WHITELIST)[number]
export function isDictEnsureType(dictType: string): dictType is DictEnsureType {
return (DICT_ENSURE_WHITELIST as readonly string[]).includes(dictType)
}
+59 -2
View File
@@ -1,5 +1,10 @@
import { defineStore } from 'pinia'
import { fetchAllDictData } from '@/api/admin'
import {
fetchAllDictData,
fetchEnsureDictData,
fetchEnsureRemoveDictData
} from '@/api/admin'
import { isDictEnsureType } from '@/constants/dict-ensure-whitelist'
interface DictItem {
label: string
@@ -11,6 +16,8 @@ export const useDictStore = defineStore('dictStore', {
state: () => ({
dictMap: {} as Record<string, DictItem[]>,
loaded: false,
/** 本会话 ensure 新插入的 value,用于下拉显示删除按钮 */
sessionCreated: {} as Record<string, string[]>
}),
getters: {
@@ -29,6 +36,11 @@ export const useDictStore = defineStore('dictStore', {
getOptions: (state) => (dictType: string): DictItem[] => {
return state.dictMap[dictType] || []
},
isSessionCreated:
(state) =>
(dictType: string, value: string): boolean => {
return (state.sessionCreated[dictType] || []).includes(value)
}
},
actions: {
@@ -45,6 +57,51 @@ export const useDictStore = defineStore('dictStore', {
clearDict() {
this.dictMap = {}
this.loaded = false
this.sessionCreated = {}
},
},
upsertLocal(dictType: string, item: { label: string; value: string; tagType?: string }) {
const list = this.dictMap[dictType] ? [...this.dictMap[dictType]] : []
const idx = list.findIndex((i) => i.value === item.value)
const row: DictItem = {
label: item.label,
value: item.value,
tagType: item.tagType || 'info'
}
if (idx >= 0) list[idx] = row
else list.push(row)
this.dictMap[dictType] = list
},
removeLocal(dictType: string, value: string) {
const list = this.dictMap[dictType] || []
this.dictMap[dictType] = list.filter((i) => i.value !== value)
const created = this.sessionCreated[dictType] || []
this.sessionCreated[dictType] = created.filter((v) => v !== value)
},
markSessionCreated(dictType: string, value: string) {
const created = this.sessionCreated[dictType] ? [...this.sessionCreated[dictType]] : []
if (!created.includes(value)) created.push(value)
this.sessionCreated[dictType] = created
},
async ensure(dictType: string, label: string, preferredValue?: string) {
const text = (label || '').trim()
if (!text) throw new Error('字典标签不能为空')
if (!isDictEnsureType(dictType)) throw new Error('不支持的字典类型')
const res = await fetchEnsureDictData({
dictType,
label: text,
preferredValue
})
const data = (res as any)?.data || res
this.upsertLocal(dictType, { label: data.label, value: data.value })
if (data.created) this.markSessionCreated(dictType, data.value)
return data as { label: string; value: string; created: boolean }
},
async ensureRemove(dictType: string, value: string) {
const v = (value || '').trim()
if (!v) throw new Error('字典值不能为空')
if (!isDictEnsureType(dictType)) throw new Error('不支持的字典类型')
await fetchEnsureRemoveDictData({ dictType, value: v })
this.removeLocal(dictType, v)
}
}
})
+3
View File
@@ -37,6 +37,9 @@
/** 列表分页默认每页条数 */
export const DEFAULT_LIST_PAGE_SIZE = 20
/** 列表分页每页条数选项(全站统一) */
export const LIST_PAGE_SIZES: number[] = [10, 20, 100, 500]
export const tableConfig = {
// 响应数据字段映射配置,系统会从接口返回数据中按顺序查找这些字段
// 列表数据
@@ -252,7 +252,7 @@
v-model:page-size="pageSize"
:total="total"
layout="total, sizes, prev, pager, next"
:page-sizes="[10, 20, 30]"
:page-sizes="[10, 20, 100, 500]"
@size-change="onSizeChange"
/>
</div>
@@ -182,7 +182,7 @@
v-model:page-size="pendingPageSize"
:total="pendingTotal"
layout="total, sizes, prev, pager, next"
:page-sizes="[10, 20, 30]"
:page-sizes="[10, 20, 100, 500]"
@size-change="onPendingSizeChange"
/>
</div>
@@ -364,7 +364,7 @@
v-model:page-size="approvedPageSize"
:total="approvedTotal"
layout="total, sizes, prev, pager, next"
:page-sizes="[10, 20, 30]"
:page-sizes="[10, 20, 100, 500]"
@size-change="onApprovedSizeChange"
/>
</div>
@@ -201,7 +201,7 @@
v-model:page-size="pageSize"
:total="total"
layout="total, sizes, prev, pager, next"
:page-sizes="[10, 20, 30]"
:page-sizes="[10, 20, 100, 500]"
@size-change="onSizeChange"
/>
</div>
@@ -399,7 +399,7 @@
v-model:page-size="pageSize"
:total="total"
layout="total, sizes, prev, pager, next"
:page-sizes="[10, 20, 30]"
:page-sizes="[10, 20, 100, 500]"
@size-change="onSizeChange"
/>
</div>
@@ -93,7 +93,7 @@
v-model:current-page="page"
v-model:page-size="pageSize"
:total="total"
:page-sizes="[10, 20, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
background
@size-change="handleSearch"
+3 -3
View File
@@ -194,7 +194,7 @@
v-model:page-size="pageSize"
:total="total"
layout="total, sizes, prev, pager, next"
:page-sizes="[10, 20, 30]"
:page-sizes="[10, 20, 100, 500]"
@size-change="onSizeChange"
/>
</div>
@@ -409,7 +409,7 @@
v-model:page-size="processedPageSize"
:total="processedTotal"
layout="total, sizes, prev, pager, next"
:page-sizes="[10, 20, 30]"
:page-sizes="[10, 20, 100, 500]"
@size-change="processedOnSizeChange"
/>
</div>
@@ -581,7 +581,7 @@
v-model:page-size="offsetAdvancePageSize"
:total="offsetAdvanceTotal"
layout="total, sizes, prev, pager, next"
:page-sizes="[5, 10, 20]"
:page-sizes="[10, 20, 100, 500]"
@current-change="fetchOffsetAdvances"
@size-change="handleOffsetAdvanceSizeChange"
/>
@@ -341,7 +341,7 @@
v-model:page-size="pageSize"
:total="total"
layout="total, sizes, prev, pager, next"
:page-sizes="[10, 20, 30, 50, 100, 200, 500]"
:page-sizes="[10, 20, 100, 500]"
@size-change="onSizeChange"
/>
</div>
@@ -231,7 +231,7 @@
v-model:page-size="pendingPageSize"
:total="pendingTotal"
layout="total, sizes, prev, pager, next"
:page-sizes="[10, 20, 30]"
:page-sizes="[10, 20, 100, 500]"
@size-change="onPendingSizeChange"
/>
</div>
@@ -462,7 +462,7 @@
v-model:page-size="approvedPageSize"
:total="approvedTotal"
layout="total, sizes, prev, pager, next"
:page-sizes="[10, 20, 30]"
:page-sizes="[10, 20, 100, 500]"
@size-change="onApprovedSizeChange"
/>
</div>
+1 -1
View File
@@ -227,7 +227,7 @@
v-model:page-size="pager.pageSize.value"
:total="pager.total.value"
layout="total, sizes, prev, pager, next"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
@size-change="pager.onSizeChange"
/>
</div>
+1 -1
View File
@@ -216,7 +216,7 @@
v-model:page-size="pageSize"
:total="filteredTotal"
layout="total, sizes, prev, pager, next"
:page-sizes="[10, 20, 30]"
:page-sizes="[10, 20, 100, 500]"
@size-change="onSizeChange"
/>
</div>
+1 -1
View File
@@ -231,7 +231,7 @@
v-model:page-size="pageSize"
:total="filteredTotal"
layout="total, sizes, prev, pager, next"
:page-sizes="[10, 20, 30]"
:page-sizes="[10, 20, 100, 500]"
@size-change="onSizeChange"
/>
</div>
@@ -117,7 +117,7 @@
v-model:current-page="followQuery.pageNum"
v-model:page-size="followQuery.pageSize"
:total="followTotal"
:page-sizes="[10, 20, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="getFollowList"
@current-change="getFollowList"
+6 -47
View File
@@ -84,21 +84,11 @@
</el-select>
</el-form-item>
<el-form-item label="所在园区" prop="parkArea">
<el-select
<DictSelect
v-model="form.parkArea"
dict-type="crm_customer_park"
placeholder="请选择或输入所在园区"
clearable
filterable
allow-create
default-first-option
>
<el-option
v-for="opt in parkAreaOptions"
:key="opt.value"
:label="opt.label"
:value="opt.value"
/>
</el-select>
/>
</el-form-item>
<el-form-item label="省份" prop="province">
<el-input v-model="form.province" placeholder="请输入省份" maxlength="50" />
@@ -176,10 +166,11 @@
<script setup lang="ts">
import { Close, Check } from '@element-plus/icons-vue'
import { getClue, addClue, updateClue, checkDuplicateClue, getParkAreaList } from '@/api/crm/clue'
import { getClue, addClue, updateClue, checkDuplicateClue } from '@/api/crm/clue'
import type { ClueForm as ClueFormType } from '@/api/crm/clue/types'
import { fetchUserOptions } from '@/api/admin'
import { useDictStore } from '@/store/modules/dict'
import DictSelect from '@/components/DictSelect/index.vue'
import { useUserStore } from '@/store/modules/user'
const dictStore = useDictStore()
@@ -224,27 +215,6 @@
})
const userList = ref<any[]>([])
const extraParkAreas = ref<string[]>([])
const parkAreaOptions = computed(() => {
const dictOpts = dictStore.getOptions('crm_customer_park')
const seen = new Set(dictOpts.map((opt) => opt.value))
const options = [...dictOpts]
for (const area of extraParkAreas.value) {
if (area && !seen.has(area)) {
options.push({ label: area, value: area, tagType: 'info' })
seen.add(area)
}
}
const current = form.value.parkArea?.trim()
if (current && !seen.has(current)) {
options.push({ label: current, value: current, tagType: 'info' })
}
return options
})
const dialog = reactive({ visible: false, title: '' })
const submitting = ref(false)
@@ -266,7 +236,7 @@
const open = async (id?: string | number) => {
reset()
dialog.visible = true
await Promise.all([loadUserList(), loadParkAreaList()])
await loadUserList()
if (id) {
dialog.title = '修改线索'
@@ -301,16 +271,6 @@
}
}
const loadParkAreaList = async () => {
try {
const res = await getParkAreaList()
const list = (res as any)?.data ?? res ?? []
extraParkAreas.value = Array.isArray(list) ? list.filter(Boolean) : []
} catch (error) {
console.error(error)
extraParkAreas.value = []
}
}
const submitForm = () => {
formRef.value?.validate(async (valid: boolean) => {
@@ -385,7 +345,6 @@
remark: undefined
}
submitting.value = false
extraParkAreas.value = []
formRef.value?.resetFields()
}
+1 -1
View File
@@ -402,7 +402,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next, jumper"
background
@size-change="getList"
@@ -478,7 +478,7 @@
v-model:current-page="queryParams.pageNum"
v-model:page-size="queryParams.pageSize"
:total="total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next, jumper"
@size-change="getList"
@current-change="getList"
@@ -173,7 +173,7 @@
<el-pagination
v-model:current-page="queryParams.pageNum"
v-model:page-size="queryParams.pageSize"
:page-sizes="[10, 20, 30, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="getList"
@@ -241,7 +241,7 @@
<el-pagination
v-model:current-page="queryParams.pageNum"
v-model:page-size="queryParams.pageSize"
:page-sizes="[10, 20, 30, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="getList"
@@ -426,16 +426,13 @@
</el-table-column>
<el-table-column label="单位" prop="unit" width="100" align="center">
<template #default="scope">
<el-select
<DictSelect
v-model="scope.row.unit"
dict-type="crm_product_unit"
placeholder="请选择单位"
clearable
size="small"
style="width: 100%"
@change="handleUnitChange(scope.row)"
>
<el-option v-for="dict in dictStore.getOptions('crm_product_unit')" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
/>
</template>
</el-table-column>
<el-table-column prop="quantity" width="130">
@@ -574,27 +571,25 @@
<el-table-column prop="packageSpec" min-width="150">
<template #header> <span style="color: #f56c6c">*</span> 包装规格</template>
<template #default="scope">
<el-select
<DictSelect
v-model="scope.row.packageSpec"
dict-type="crm_product_gg"
placeholder="请选择包装规格"
filterable
allow-create
default-first-option
clearable
size="small"
style="width: 100%"
@change="handlePackageSpecChange(scope.row, $event)"
>
<el-option v-for="dict in dictStore.getOptions('crm_product_gg')" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
/>
</template>
</el-table-column>
<el-table-column prop="deliveryMethod" min-width="150">
<template #header> <span style="color: #f56c6c">*</span> 送货方式</template>
<template #default="scope">
<el-select v-model="scope.row.deliveryMethod" placeholder="请选择送货方式" clearable size="small" style="width: 100%">
<el-option v-for="dict in dictStore.getOptions('crm_shfs')" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
<DictSelect
v-model="scope.row.deliveryMethod"
dict-type="crm_shfs"
placeholder="请选择送货方式"
size="small"
style="width: 100%"
/>
</template>
</el-table-column>
<el-table-column prop="remark" label="备注" min-width="160">
@@ -831,7 +826,7 @@ import {
type ContractProductForm,
type ContractProductPriceTierForm
} from '@/api/crm/contract/index'
import { isFrameworkContractType } from '../contractType'
import { isFrameworkContractType, isPurchaseLikeContractType } from '../contractType'
import {
FRAMEWORK_QUANTITY_LABEL,
FRAMEWORK_PRICE_LABEL,
@@ -879,6 +874,7 @@ import { getOpportunity } from '@/api/crm/opportunity'
import { getQuote } from '@/api/crm/quote'
import ProductSelector from '@/components/business/product-selector/index.vue'
import ProductAliasBrandDialog from '@/components/business/product-alias-brand-dialog/index.vue'
import DictSelect from '@/components/DictSelect/index.vue'
import CustomerSelector from '@/components/CustomerSelector.vue'
import ContactSelector from '@/components/ContactSelector.vue'
import ContactFormDialog from '@/views/crm/customer/components/ContactFormDialog.vue'
@@ -2268,9 +2264,9 @@ const handleContractTypeChange = (value: string) => {
})
calculateTotalAmount()
}
if (value === 'purchase' && !isPartiesSwapped.value) {
if (isPurchaseLikeContractType(value) && !isPartiesSwapped.value) {
$modal
.confirm('检测到您选择了采购合同,系统将自动调换供需方信息,是否继续?')
.confirm('检测到您选择了采购类合同,系统将自动调换供需方信息,是否继续?')
.then(async () => {
await handleSwapParties()
})
@@ -2502,16 +2498,6 @@ const handleTaxRateChange = (row: ExtendedContractProductForm) => {
calculateTotalAmount()
}
/** 单位变化 */
const handleUnitChange = (_row: ExtendedContractProductForm) => {
// 单位变化通常不需要重新计算金额
}
/** 包装规格变更处理 */
const handlePackageSpecChange = (product: ExtendedContractProductForm, value: string) => {
product.packageSpec = value
}
const handleEnableFrameworkQuantityFixed = (row: ExtendedContractProductForm) => {
enableFrameworkQuantityFixed(row)
calculateProductAmount(row)
@@ -11,6 +11,15 @@ export function isFrameworkContractType(type?: string | null): boolean {
return FRAMEWORK_CONTRACT_TYPES.includes((type || '').trim() as FrameworkContractType)
}
/** 采购类合同(含框架采购):选择后需提示并调换供需方 */
export const PURCHASE_LIKE_CONTRACT_TYPES = ['purchase', 'framework_purchase'] as const
export type PurchaseLikeContractType = (typeof PURCHASE_LIKE_CONTRACT_TYPES)[number]
export function isPurchaseLikeContractType(type?: string | null): boolean {
return PURCHASE_LIKE_CONTRACT_TYPES.includes((type || '').trim() as PurchaseLikeContractType)
}
/** 允许打开编辑的合同状态(保存后回草稿) */
export const CONTRACT_EDITABLE_STATUSES = ['draft', 'approving', 'approved'] as const
+18 -33
View File
@@ -292,16 +292,13 @@
</el-table-column>
<el-table-column label="单位" prop="unit" width="100" align="center">
<template #default="scope">
<el-select
<DictSelect
v-model="scope.row.unit"
dict-type="crm_product_unit"
placeholder="请选择单位"
clearable
size="small"
style="width: 100%"
@change="handleUnitChange(scope.row)"
>
<el-option v-for="dict in dictStore.getOptions('crm_product_unit')" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
/>
</template>
</el-table-column>
<el-table-column prop="quantity" width="130">
@@ -370,27 +367,25 @@
<el-table-column prop="packageSpec" min-width="150">
<template #header> <span style="color: #f56c6c">*</span> 包装规格</template>
<template #default="scope">
<el-select
<DictSelect
v-model="scope.row.packageSpec"
dict-type="crm_product_gg"
placeholder="请选择包装规格"
filterable
allow-create
default-first-option
clearable
size="small"
style="width: 100%"
@change="(val) => handlePackageSpecChange(scope.row, val)"
>
<el-option v-for="dict in dictStore.getOptions('crm_product_gg')" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
/>
</template>
</el-table-column>
<el-table-column prop="deliveryMethod" min-width="150">
<template #header> <span style="color: #f56c6c">*</span> 送货方式</template>
<template #default="scope">
<el-select v-model="scope.row.deliveryMethod" placeholder="请选择送货方式" clearable size="small" style="width: 100%">
<el-option v-for="dict in dictStore.getOptions('crm_shfs')" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
<DictSelect
v-model="scope.row.deliveryMethod"
dict-type="crm_shfs"
placeholder="请选择送货方式"
size="small"
style="width: 100%"
/>
</template>
</el-table-column>
<el-table-column prop="remark" label="备注" min-width="160">
@@ -546,7 +541,7 @@ import {
type ContractProductForm,
type ContractProductPriceTierForm
} from '@/api/crm/contract/index';
import { isFrameworkContractType } from './contractType';
import { isFrameworkContractType, isPurchaseLikeContractType } from './contractType';
import {
FRAMEWORK_QUANTITY_LABEL,
FRAMEWORK_PRICE_LABEL,
@@ -579,6 +574,7 @@ import AttachmentUploadField from '@/components/business/attachment-upload-field
import { getOpportunity } from '@/api/crm/opportunity';
import { getQuote } from '@/api/crm/quote';
import ProductSelector from '@/components/business/product-selector/index.vue';
import DictSelect from '@/components/DictSelect/index.vue'
import CustomerSelector from '@/components/CustomerSelector.vue';
import ContactSelector from '@/components/ContactSelector.vue';
import QuoteSelector from '@/components/QuoteSelector.vue';
@@ -1409,10 +1405,10 @@ const handleContractTypeChange = (value: string) => {
});
calculateTotalAmount();
}
// 当选择采购合同时,自动调换供需方
if (value === 'purchase' && !isPartiesSwapped.value) {
// 当选择采购类合同时,自动调换供需方
if (isPurchaseLikeContractType(value) && !isPartiesSwapped.value) {
$modal
.confirm('检测到您选择了采购合同,系统将自动调换供需方信息,是否继续?')
.confirm('检测到您选择了采购类合同,系统将自动调换供需方信息,是否继续?')
.then(() => {
handleSwapParties();
})
@@ -1596,17 +1592,6 @@ const handleTaxRateChange = (row: ExtendedContractProductForm) => {
calculateTotalAmount();
};
/** 单位变化 */
const handleUnitChange = (row: ExtendedContractProductForm) => {
// 单位变化通常不需要重新计算金额,但可以在这里添加其他逻辑
// 例如:记录变更日志、验证单位有效性等
};
/** 包装规格变更处理(支持自由输入并写入字典) */
const handlePackageSpecChange = (product: ExtendedContractProductForm, value: string) => {
product.packageSpec = value;
};
const handleEnableFrameworkQuantityFixed = (row: ExtendedContractProductForm) => {
enableFrameworkQuantityFixed(row);
calculateProductAmount(row);
@@ -186,7 +186,7 @@
<el-pagination
v-model:current-page="queryParams.pageNum"
v-model:page-size="queryParams.pageSize"
:page-sizes="[10, 20, 30, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="getList"
@@ -100,7 +100,7 @@
v-model:current-page="followQuery.pageNum"
v-model:page-size="followQuery.pageSize"
:total="followTotal"
:page-sizes="[10, 20, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="getFollowList"
@current-change="getFollowList"
@@ -430,7 +430,7 @@
v-model:current-page="logQuery.pageNum"
v-model:page-size="logQuery.pageSize"
:total="logTotal"
:page-sizes="[10, 20, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="() => getOperLogList(false)"
@current-change="() => getOperLogList(false)"
@@ -104,21 +104,11 @@
</el-select>
</el-form-item>
<el-form-item label="所在园区" prop="parkArea">
<el-select
<DictSelect
v-model="form.parkArea"
dict-type="crm_customer_park"
placeholder="请选择或输入所在园区"
clearable
filterable
allow-create
default-first-option
>
<el-option
v-for="opt in parkAreaOptions"
:key="opt.value"
:label="opt.label"
:value="opt.value"
/>
</el-select>
/>
</el-form-item>
<el-form-item label="企业规模" prop="scale">
<el-select v-model="form.scale" placeholder="请选择企业规模" clearable>
@@ -323,15 +313,14 @@
</template>
<script setup lang="ts">
import { ref, reactive, computed, nextTick } from 'vue'
import { ref, reactive, nextTick } from 'vue'
import { Close, Check, Refresh, DocumentCopy, Delete } from '@element-plus/icons-vue'
import type { FormItemRule } from 'element-plus'
import { ElMessage } from 'element-plus'
import {
fetchCustomerDetail,
fetchCreateCustomer,
fetchUpdateCustomer,
fetchParkAreaList
fetchUpdateCustomer
} from '@/api/crm/customer'
import type { CustomerForm as CustomerFormType } from '@/api/crm/customerTypes'
import { addInvoiceInfo } from '@/api/crm/invoiceInfo'
@@ -341,6 +330,7 @@ import {
mergeInvoiceRemark
} from '@/utils/crm-invoice-paste-recognize'
import { useDictStore } from '@/store/modules/dict'
import DictSelect from '@/components/DictSelect/index.vue'
import { useUserStore } from '@/store/modules/user'
import { fetchUserOptions } from '@/api/admin'
import AttachmentUploadField from '@/components/business/attachment-upload-field/index.vue'
@@ -402,7 +392,6 @@ const rules = ref<Record<string, FormItemRule[]>>({
// 用户列表
const userList = ref<any[]>([])
const extraParkAreas = ref<string[]>([])
const invoiceForm = ref<InvoiceInfoForm>({
companyName: '',
@@ -416,25 +405,6 @@ const invoiceForm = ref<InvoiceInfoForm>({
remark: ''
})
const parkAreaOptions = computed(() => {
const dictOpts = dictStore.getOptions('crm_customer_park')
const seen = new Set(dictOpts.map((opt) => opt.value))
const options = [...dictOpts]
for (const area of extraParkAreas.value) {
if (area && !seen.has(area)) {
options.push({ label: area, value: area, tagType: 'info' })
seen.add(area)
}
}
const current = form.value.parkArea?.trim()
if (current && !seen.has(current)) {
options.push({ label: current, value: current, tagType: 'info' })
}
return options
})
// 对话框
const dialog = reactive({
@@ -482,17 +452,6 @@ const applyDefaultOwnerUserId = async () => {
form.value.ownerUserId = defaultOwnerUserId as CustomerFormType['ownerUserId']
}
/** 加载历史园区列表 */
const loadParkAreaList = async () => {
try {
const res = await fetchParkAreaList()
const list = unwrapApiData(res as string[] | { data?: string[] })
extraParkAreas.value = Array.isArray(list) ? list.filter(Boolean) : []
} catch (error) {
console.error(error)
extraParkAreas.value = []
}
}
function hasInvoiceInfoFilled() {
const inv = invoiceForm.value
@@ -601,7 +560,7 @@ const open = async (id?: number | string) => {
reset()
dialog.visible = true
await Promise.all([loadUserList(), loadParkAreaList()])
await loadUserList()
if (id) {
dialog.title = '修改客户'
+1 -1
View File
@@ -615,7 +615,7 @@
<el-pagination
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:page-sizes="[10, 20, 30, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next, jumper"
:total="pagination.total"
@size-change="getList"
@@ -210,7 +210,7 @@
<el-pagination
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:page-sizes="[10, 20, 30, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next, jumper"
:total="pagination.total"
@size-change="getList"
@@ -506,7 +506,7 @@
<el-pagination
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:page-sizes="[10, 20, 30, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next, jumper"
:total="pagination.total"
@size-change="getList"
@@ -454,7 +454,7 @@
v-model:current-page="queryParams.pageNum"
v-model:page-size="queryParams.pageSize"
:total="total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next, jumper"
background
@size-change="getList"
@@ -249,7 +249,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next, jumper"
background
@size-change="getList"
+1 -1
View File
@@ -275,7 +275,7 @@
<el-pagination
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:page-sizes="[10, 20, 30, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next, jumper"
:total="pagination.total"
@size-change="handlePageSizeChange"
@@ -443,7 +443,7 @@
v-model:current-page="queryParams.pageNum"
v-model:page-size="queryParams.pageSize"
:total="total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next, jumper"
@size-change="getList"
@current-change="getList"
@@ -275,18 +275,13 @@
</el-table-column>
<el-table-column label="单位" prop="unit" width="100" align="center">
<template #default="scope">
<el-select
<DictSelect
v-model="scope.row.unit"
dict-type="crm_product_unit"
placeholder="请选择单位"
filterable
allow-create
default-first-option
size="small"
style="width: 100%"
@change="(val) => handleUnitChange(scope.row, val)"
>
<el-option v-for="dict in dictStore.getOptions('crm_product_unit')" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
/>
</template>
</el-table-column>
<el-table-column prop="quantity" width="110">
@@ -321,27 +316,25 @@
<el-table-column prop="packageSpec" min-width="150">
<template #header> <span style="color: #f56c6c">*</span> 包装规格</template>
<template #default="scope">
<el-select
<DictSelect
v-model="scope.row.packageSpec"
dict-type="crm_product_gg"
placeholder="请选择包装规格"
filterable
allow-create
default-first-option
clearable
size="small"
style="width: 100%"
@change="(val) => handlePackageSpecChange(scope.row, val)"
>
<el-option v-for="dict in dictStore.getOptions('crm_product_gg')" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
/>
</template>
</el-table-column>
<el-table-column prop="deliveryMethod" min-width="150">
<template #header> <span style="color: #f56c6c">*</span> 送货方式</template>
<template #default="scope">
<el-select v-model="scope.row.deliveryMethod" placeholder="请选择送货方式" clearable size="small" style="width: 100%">
<el-option v-for="dict in dictStore.getOptions('crm_shfs')" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
<DictSelect
v-model="scope.row.deliveryMethod"
dict-type="crm_shfs"
placeholder="请选择送货方式"
size="small"
style="width: 100%"
/>
</template>
</el-table-column>
<el-table-column label="操作" min-width="80" align="center" header-align="center" fixed="right" class-name="col-actions">
@@ -654,6 +647,7 @@ import {
import ImagePreview from '@/components/ImagePreview/index.vue';
import ProductSelector from '@/components/business/product-selector/index.vue';
import ProductAliasBrandDialog from '@/components/business/product-alias-brand-dialog/index.vue'
import DictSelect from '@/components/DictSelect/index.vue'
import CustomerSelector from '@/components/CustomerSelector.vue';
import ContactSelector from '@/components/ContactSelector.vue';
import ContactFormDialog from '@/views/crm/customer/components/ContactFormDialog.vue'
@@ -1833,16 +1827,6 @@ const normalizeTaxRateDisplay = (value: any, defaultValue = 0): number => {
return Number.isInteger(num) ? num : parseFloat(num.toString());
};
/** 单位变更处理(支持自由输入并写入字典) */
const handleUnitChange = (product: QuoteProductForm, value: string) => {
product.unit = value;
};
/** 包装规格变更处理(支持自由输入并写入字典) */
const handlePackageSpecChange = (product: QuoteProductForm, value: string) => {
product.packageSpec = value;
};
/** 单价变更 */
const handlePriceChange = (product: QuoteProductForm) => {
calculateProductAmount(product);
@@ -67,7 +67,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
background
@size-change="loadData"
+1 -1
View File
@@ -376,7 +376,7 @@
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:total="total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next, jumper"
@current-change="handlePageChange"
@size-change="handleSizeChange"
+1 -1
View File
@@ -310,7 +310,7 @@
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:total="total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next, jumper"
@current-change="loadData"
@size-change="loadData"
+1 -1
View File
@@ -326,7 +326,7 @@
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:total="total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next, jumper"
@current-change="handlePageChange"
@size-change="handleSizeChange"
+1 -1
View File
@@ -303,7 +303,7 @@
:current-page="pagination.page"
:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next, jumper"
@update:current-page="
(v) => {
+1 -1
View File
@@ -228,7 +228,7 @@
:current-page="pagination.page"
:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next, jumper"
@update:current-page="(val) => (pagination.page = val)"
@update:page-size="(val) => (pagination.pageSize = val)"
+1 -1
View File
@@ -134,7 +134,7 @@
:current-page="pagination.page"
:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="(val) => ((pagination.page = 1), (pagination.pageSize = val), loadData())"
@current-change="(val) => ((pagination.page = val), loadData())"
@@ -223,7 +223,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next, jumper"
@current-change="fetchData"
@size-change="fetchData"
+1 -1
View File
@@ -189,7 +189,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="handleSizeChange"
@current-change="handlePageChange"
+1 -1
View File
@@ -163,7 +163,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="handleSizeChange"
@current-change="handlePageChange"
@@ -154,7 +154,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="handleSizeChange"
@current-change="handlePageChange"
@@ -166,7 +166,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="handleSizeChange"
@current-change="handlePageChange"
@@ -143,7 +143,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="handleSizeChange"
@current-change="handlePageChange"
@@ -136,7 +136,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="handleSizeChange"
@current-change="handlePageChange"
@@ -256,7 +256,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="handleSizeChange"
@current-change="handlePageChange"
@@ -199,7 +199,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="handleSizeChange"
@current-change="handlePageChange"
+1 -1
View File
@@ -163,7 +163,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="handleSizeChange"
@current-change="handlePageChange"
+1 -1
View File
@@ -262,7 +262,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="handleSizeChange"
@current-change="handlePageChange"
@@ -175,9 +175,7 @@
align="center"
>
<template #default="{ row }">
<el-tag :type="getPlanTypeTagType(row.planType)" size="small">
{{ getPlanTypeLabel(row.planType) }}
</el-tag>
{{ getPlanTypeLabel(row.planType) }}
</template>
</el-table-column>
<el-table-column
@@ -316,7 +314,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="handleSizeChange"
@current-change="handlePageChange"
@@ -517,11 +515,6 @@ const pagination = reactive({
total: 0
})
function getPlanTypeTagType(type: string) {
const map: Record<string, string> = { direct: 'primary', inbound: 'success', outbound: 'warning' }
return map[type] || 'info'
}
function getPlanTypeLabel(type: string) {
const map: Record<string, string> = { direct: '直销单', inbound: '入库单', outbound: '出库单' }
return map[type] || type
+2 -9
View File
@@ -209,9 +209,7 @@
align="center"
>
<template #default="{ row }">
<el-tag :type="getPlanTypeTagType(row.planType)" size="small">
{{ getPlanTypeLabel(row.planType) }}
</el-tag>
{{ getPlanTypeLabel(row.planType) }}
</template>
</el-table-column>
<el-table-column
@@ -351,7 +349,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="handleSizeChange"
@current-change="handlePageChange"
@@ -499,11 +497,6 @@ const pagination = reactive({
total: 0
})
function getPlanTypeTagType(type: string) {
const map: Record<string, string> = { direct: 'primary', inbound: 'success', outbound: 'warning' }
return map[type] || 'info'
}
function getPlanTypeLabel(type: string) {
const map: Record<string, string> = { direct: '直销单', inbound: '入库单', outbound: '出库单' }
return map[type] || type
@@ -318,7 +318,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next, jumper"
background
@current-change="handlePageChange"
+1 -1
View File
@@ -431,7 +431,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="handleSizeChange"
@current-change="handlePageChange"
@@ -237,7 +237,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="handleSizeChange"
@current-change="handlePageChange"
@@ -160,7 +160,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next, jumper"
@current-change="handlePageChange"
@size-change="handleSizeChange"
+1 -1
View File
@@ -204,7 +204,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="handleSizeChange"
@current-change="handlePageChange"
@@ -219,7 +219,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="fetchData"
@current-change="fetchData"
@@ -265,7 +265,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="fetchData"
@current-change="fetchData"
@@ -189,7 +189,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="fetchData"
@current-change="fetchData"
@@ -270,7 +270,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="fetchData"
@current-change="fetchData"
@@ -204,7 +204,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="fetchData"
@current-change="fetchData"
@@ -250,7 +250,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="fetchData"
@current-change="fetchData"
+1 -1
View File
@@ -244,7 +244,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50, 100]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="handleSizeChange"
@current-change="handlePageChange"
+2 -2
View File
@@ -148,7 +148,7 @@
:current-page="pagination.page"
:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="(val) => ((pagination.page = 1), (pagination.pageSize = val), loadData())"
@current-change="(val) => ((pagination.page = val), loadData())"
@@ -419,7 +419,7 @@
:current-page="dictDataPagination.page"
:page-size="dictDataPagination.pageSize"
:total="dictDataPagination.total"
:page-sizes="[10, 20, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="
(val) => (
+1 -1
View File
@@ -181,7 +181,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="loadData"
@current-change="loadData"
+1 -1
View File
@@ -166,7 +166,7 @@
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next, jumper"
@size-change="fetchList"
@current-change="fetchList"
+1 -1
View File
@@ -155,7 +155,7 @@
:current-page="pagination.page"
:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="(val) => ((pagination.page = 1), (pagination.pageSize = val), loadData())"
@current-change="(val) => ((pagination.page = val), loadData())"
+1 -1
View File
@@ -172,7 +172,7 @@
:current-page="pagination.page"
:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="
(val: number) => ((pagination.page = 1), (pagination.pageSize = val), loadData())
+1 -1
View File
@@ -172,7 +172,7 @@
:current-page="pagination.page"
:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="(val) => ((pagination.page = 1), (pagination.pageSize = val), loadData())"
@current-change="(val) => ((pagination.page = val), loadData())"
+1 -1
View File
@@ -177,7 +177,7 @@
:current-page="pagination.page"
:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="(val) => ((pagination.page = 1), (pagination.pageSize = val), loadData())"
@current-change="(val) => ((pagination.page = val), loadData())"
+1 -1
View File
@@ -229,7 +229,7 @@
:current-page="pagination.page"
:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="
(val: number) => ((pagination.page = 1), (pagination.pageSize = val), loadData())
@@ -134,7 +134,7 @@
:current-page="pagination.page"
:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="(val) => ((pagination.page = 1), (pagination.pageSize = val), loadData())"
@current-change="(val) => ((pagination.page = val), loadData())"
@@ -174,7 +174,7 @@
:current-page="pagination.page"
:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="(val) => ((pagination.page = 1), (pagination.pageSize = val), loadData())"
@current-change="(val) => ((pagination.page = val), loadData())"
@@ -137,7 +137,7 @@
:current-page="pagination.page"
:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="(val) => ((pagination.page = 1), (pagination.pageSize = val), loadData())"
@current-change="(val) => ((pagination.page = val), loadData())"
@@ -132,7 +132,7 @@
:current-page="pagination.page"
:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50]"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="(val) => ((pagination.page = 1), (pagination.pageSize = val), loadData())"
@current-change="(val) => ((pagination.page = val), loadData())"