提交
This commit is contained in:
1 parent
6dc8cfb2c1
commit
d26fb23fcf
181 files changed
+25727
-24557
No files matched your search
@@ -198,7 +198,6 @@
|
||||
"196": "Community 196",
|
||||
"197": "v2.4.2.1 - 2025-06-16",
|
||||
"198": "fetchRoleOptions",
|
||||
"199": "price-letter-template.ts",
|
||||
"200": "index.js",
|
||||
"201": "Ha",
|
||||
"202": "Community 202",
|
||||
@@ -235,29 +234,30 @@
|
||||
"233": "Community 233",
|
||||
"234": "Community 234",
|
||||
"235": "index.js",
|
||||
"236": "fetchData",
|
||||
"236": "fastEnter.ts",
|
||||
"237": "DbPoundSlipQrcodeDialog.vue",
|
||||
"238": "pl-plan-contract-display.ts",
|
||||
"239": "Community 239",
|
||||
"240": "weighing.ts",
|
||||
"240": "detail.vue",
|
||||
"241": "index.vue",
|
||||
"242": "Community 242",
|
||||
"243": "Community 243",
|
||||
"244": "expenseItemCode.ts",
|
||||
"244": "loadUserOptions",
|
||||
"245": "index.js",
|
||||
"246": "handleSearch",
|
||||
"246": "getPlMaintenanceApplyStatusLabel",
|
||||
"247": "Community 247",
|
||||
"248": "Community 248",
|
||||
"249": "crm-product-display.ts",
|
||||
"250": "handleAdd",
|
||||
"251": "handleDisburse",
|
||||
"252": "detail.vue",
|
||||
"252": "index.js",
|
||||
"253": "Community 253",
|
||||
"254": "fetchDesignerData",
|
||||
"255": "Community 255",
|
||||
"256": "handleOpen",
|
||||
"259": "Community 259",
|
||||
"260": "Community 260",
|
||||
"261": "Community 261",
|
||||
"262": "form.vue",
|
||||
"263": "index.vue",
|
||||
"265": "Community 265",
|
||||
"269": "Community 269",
|
||||
"270": "Community 270",
|
||||
@@ -335,7 +335,6 @@
|
||||
"425": "Community 425",
|
||||
"426": "Community 426",
|
||||
"427": "Community 427",
|
||||
"428": "Community 428",
|
||||
"435": "index.vue",
|
||||
"443": "index.vue",
|
||||
"444": "index.vue",
|
||||
@@ -504,7 +503,6 @@
|
||||
"1200": "index.js",
|
||||
"1201": "index.js",
|
||||
"1202": "index.js",
|
||||
"1203": "index.js",
|
||||
"1204": "plugin.js",
|
||||
"1205": "plugin.min.js",
|
||||
"1206": "index.js",
|
||||
|
||||
@@ -138,6 +138,7 @@
|
||||
"136": "Community 136",
|
||||
"137": "Community 137",
|
||||
"138": "FollowDialog.vue",
|
||||
"139": "RenewDialog.vue",
|
||||
"140": "Community 140",
|
||||
"141": "Community 141",
|
||||
"142": "Community 142",
|
||||
@@ -145,6 +146,7 @@
|
||||
"144": "Community 144",
|
||||
"145": "api",
|
||||
"146": "price-letter-template.ts",
|
||||
"147": "index.vue",
|
||||
"148": "Community 148",
|
||||
"149": "fetchCustomerDetail",
|
||||
"150": "Community 150",
|
||||
@@ -233,27 +235,30 @@
|
||||
"233": "Community 233",
|
||||
"234": "Community 234",
|
||||
"235": "index.js",
|
||||
"236": "fetchData",
|
||||
"236": "fastEnter.ts",
|
||||
"237": "DbPoundSlipQrcodeDialog.vue",
|
||||
"238": "pl-plan-contract-display.ts",
|
||||
"239": "Community 239",
|
||||
"240": "detail.vue",
|
||||
"241": "index.vue",
|
||||
"242": "Community 242",
|
||||
"243": "Community 243",
|
||||
"244": "loadUserOptions",
|
||||
"245": "index.js",
|
||||
"246": "getPlMaintenanceApplyStatusLabel",
|
||||
"247": "Community 247",
|
||||
"248": "Community 248",
|
||||
"249": "crm-product-display.ts",
|
||||
"250": "handleAdd",
|
||||
"251": "handleDisburse",
|
||||
"252": "detail.vue",
|
||||
"252": "index.js",
|
||||
"253": "Community 253",
|
||||
"254": "fetchDesignerData",
|
||||
"255": "Community 255",
|
||||
"258": "getPlMaintenanceApplyStatusLabel",
|
||||
"256": "handleOpen",
|
||||
"259": "Community 259",
|
||||
"260": "Community 260",
|
||||
"261": "Community 261",
|
||||
"262": "form.vue",
|
||||
"263": "index.vue",
|
||||
"265": "Community 265",
|
||||
"269": "Community 269",
|
||||
"270": "Community 270",
|
||||
@@ -331,7 +336,6 @@
|
||||
"425": "Community 425",
|
||||
"426": "Community 426",
|
||||
"427": "Community 427",
|
||||
"428": "Community 428",
|
||||
"435": "index.vue",
|
||||
"443": "index.vue",
|
||||
"444": "index.vue",
|
||||
@@ -500,7 +504,6 @@
|
||||
"1200": "index.js",
|
||||
"1201": "index.js",
|
||||
"1202": "index.js",
|
||||
"1203": "index.js",
|
||||
"1204": "plugin.js",
|
||||
"1205": "plugin.min.js",
|
||||
"1206": "index.js",
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
+5243
-4590
File diff suppressed because it is too large.
Load diff
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -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"
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 = '修改客户'
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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)"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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) => (
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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())"
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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())"
|
||||
|
||||
@@ -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())"
|
||||
|
||||
@@ -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())"
|
||||
|
||||
Reference in new issue
Block a user