(no commit message provided)
Co-authored-by: aider (openai/DeepSeek-V3.2-Thinking) <aider@aider.chat>
This commit is contained in:
@ -6,6 +6,22 @@ from app.services.inbound.service_service import ServiceService
|
|||||||
from app.utils.decorators import role_required
|
from app.utils.decorators import role_required
|
||||||
|
|
||||||
|
|
||||||
|
@inbound_bp.route('/service/search-base', methods=['GET'])
|
||||||
|
@jwt_required()
|
||||||
|
def search_base():
|
||||||
|
"""搜索基础物料"""
|
||||||
|
keyword = request.args.get('keyword', '')
|
||||||
|
try:
|
||||||
|
data = ServiceService.search_base_material(keyword)
|
||||||
|
return jsonify({
|
||||||
|
'code': 200,
|
||||||
|
'msg': 'success',
|
||||||
|
'data': data
|
||||||
|
})
|
||||||
|
except Exception as e:
|
||||||
|
current_app.logger.error(f'搜索基础物料失败: {str(e)}')
|
||||||
|
return jsonify({'code': 500, 'msg': '内部服务器错误'}), 500
|
||||||
|
|
||||||
@inbound_bp.route('/service', methods=['GET'])
|
@inbound_bp.route('/service', methods=['GET'])
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
def get_service_list():
|
def get_service_list():
|
||||||
|
|||||||
@ -33,6 +33,35 @@ class ServiceService:
|
|||||||
suffix = str(suffix_num).zfill(cls.SKU_SUFFIX_LEN)
|
suffix = str(suffix_num).zfill(cls.SKU_SUFFIX_LEN)
|
||||||
return f'{prefix}{suffix}'
|
return f'{prefix}{suffix}'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def search_base_material(cls, keyword):
|
||||||
|
"""搜索基础物料,供前端远程选择"""
|
||||||
|
try:
|
||||||
|
query = MaterialBase.query.filter(MaterialBase.is_enabled == True)
|
||||||
|
if keyword:
|
||||||
|
query = query.filter(
|
||||||
|
db.or_(
|
||||||
|
MaterialBase.name.ilike(f'%{keyword}%'),
|
||||||
|
MaterialBase.spec_model.ilike(f'%{keyword}%'),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
query = query.order_by(MaterialBase.id.desc()).limit(20)
|
||||||
|
results = []
|
||||||
|
for item in query.all():
|
||||||
|
results.append({
|
||||||
|
'id': item.id,
|
||||||
|
'name': item.name,
|
||||||
|
'spec': item.spec_model,
|
||||||
|
'category': item.category,
|
||||||
|
'unit': item.unit,
|
||||||
|
'type': item.material_type,
|
||||||
|
})
|
||||||
|
return results
|
||||||
|
except Exception as e:
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
return []
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_service(cls, data):
|
def create_service(cls, data):
|
||||||
"""创建服务权益记录"""
|
"""创建服务权益记录"""
|
||||||
|
|||||||
@ -47,6 +47,15 @@ export interface ServiceUpdateRequest {
|
|||||||
description?: string
|
description?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface MaterialBaseItem {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
spec: string
|
||||||
|
category: string
|
||||||
|
unit: string
|
||||||
|
type: string
|
||||||
|
}
|
||||||
|
|
||||||
// 获取服务权益列表
|
// 获取服务权益列表
|
||||||
export function getServiceList(params: ServiceQueryParams) {
|
export function getServiceList(params: ServiceQueryParams) {
|
||||||
return request<ServiceListResponse>({
|
return request<ServiceListResponse>({
|
||||||
@ -82,6 +91,19 @@ export function updateService(id: number, data: ServiceUpdateRequest) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 搜索基础物料
|
||||||
|
export function searchMaterialBase(keyword: string) {
|
||||||
|
return request<{
|
||||||
|
code: number
|
||||||
|
msg: string
|
||||||
|
data: MaterialBaseItem[]
|
||||||
|
}>({
|
||||||
|
url: '/v1/inbound/service/search-base',
|
||||||
|
method: 'get',
|
||||||
|
params: { keyword }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 删除服务权益
|
// 删除服务权益
|
||||||
export function deleteService(id: number) {
|
export function deleteService(id: number) {
|
||||||
return request({
|
return request({
|
||||||
|
|||||||
@ -87,15 +87,52 @@
|
|||||||
@close="resetDialog"
|
@close="resetDialog"
|
||||||
>
|
>
|
||||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
|
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
|
||||||
<el-form-item label="基础物料ID" prop="base_id">
|
<el-row :gutter="24" v-if="dialogStatus === 'create'" style="margin-bottom: 15px;">
|
||||||
<el-input-number
|
<el-col :span="10">
|
||||||
|
<el-form-item label="物料搜索" prop="base_id" class="highlight-label">
|
||||||
|
<el-select
|
||||||
v-model="form.base_id"
|
v-model="form.base_id"
|
||||||
placeholder="请输入基础物料ID"
|
filterable
|
||||||
:controls="false"
|
remote
|
||||||
style="width: 100%;"
|
reserve-keyword
|
||||||
/>
|
placeholder="输入名称或规格..."
|
||||||
<div style="font-size:12px;color:#999;">需要先创建基础物料</div>
|
:remote-method="handleSearchMaterial"
|
||||||
|
@visible-change="handleMaterialDropdownVisible"
|
||||||
|
:loading="searchLoading"
|
||||||
|
style="width: 100%"
|
||||||
|
@change="onMaterialSelected"
|
||||||
|
default-first-option
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in materialOptions"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.id"
|
||||||
|
>
|
||||||
|
<div class="option-item">
|
||||||
|
<span class="opt-name">{{ item.name }}</span>
|
||||||
|
<span class="opt-spec">{{ item.spec }}</span>
|
||||||
|
</div>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="14" style="display: flex; align-items: center;">
|
||||||
|
<span class="search-tip">
|
||||||
|
<el-icon><InfoFilled/></el-icon> 未输入时展示最新物料;输入关键词进行精确搜索。
|
||||||
|
</span>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<div class="read-only-grid" v-if="form.base_id">
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="8"><el-form-item label="名称"><el-input v-model="form.material_name" disabled class="is-text-view"/></el-form-item></el-col>
|
||||||
|
<el-col :span="8"><el-form-item label="类型"><el-input v-model="form.material_type" disabled class="is-text-view"/></el-form-item></el-col>
|
||||||
|
<el-col :span="8"><el-form-item label="类别"><el-input v-model="form.category" disabled class="is-text-view"/></el-form-item></el-col>
|
||||||
|
<el-col :span="8"><el-form-item label="规格型号"><el-input v-model="form.spec_model" disabled class="is-text-view"/></el-form-item></el-col>
|
||||||
|
<el-col :span="8"><el-form-item label="单位"><el-input v-model="form.unit" disabled class="is-text-view"/></el-form-item></el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
<el-form-item label="售价" prop="sale_price">
|
<el-form-item label="售价" prop="sale_price">
|
||||||
<el-input-number
|
<el-input-number
|
||||||
v-model="form.sale_price"
|
v-model="form.sale_price"
|
||||||
@ -133,6 +170,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, reactive, onMounted } from 'vue'
|
import { ref, reactive, onMounted } from 'vue'
|
||||||
|
import { InfoFilled } from '@element-plus/icons-vue'
|
||||||
import type { FormInstance, FormRules } from 'element-plus'
|
import type { FormInstance, FormRules } from 'element-plus'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import {
|
import {
|
||||||
@ -140,9 +178,11 @@ import {
|
|||||||
createService,
|
createService,
|
||||||
updateService,
|
updateService,
|
||||||
deleteService,
|
deleteService,
|
||||||
|
searchMaterialBase,
|
||||||
type ServiceItem,
|
type ServiceItem,
|
||||||
type ServiceQueryParams,
|
type ServiceQueryParams,
|
||||||
type ServiceCreateRequest
|
type ServiceCreateRequest,
|
||||||
|
type MaterialBaseItem
|
||||||
} from '@/api/inbound/service'
|
} from '@/api/inbound/service'
|
||||||
|
|
||||||
// 表格数据
|
// 表格数据
|
||||||
@ -152,6 +192,9 @@ const page = ref(1)
|
|||||||
const perPage = ref(20)
|
const perPage = ref(20)
|
||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
|
|
||||||
|
const materialOptions = ref<any[]>([])
|
||||||
|
const searchLoading = ref(false)
|
||||||
|
|
||||||
const searchForm = reactive({
|
const searchForm = reactive({
|
||||||
keyword: '',
|
keyword: '',
|
||||||
provider_name: '',
|
provider_name: '',
|
||||||
@ -209,6 +252,39 @@ const handlePageChange = (val: number) => {
|
|||||||
loadData()
|
loadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleMaterialDropdownVisible = (visible: boolean) => {
|
||||||
|
if (visible && materialOptions.value.length === 0) {
|
||||||
|
handleSearchMaterial('')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSearchMaterial = async (query: string) => {
|
||||||
|
searchLoading.value = true
|
||||||
|
try {
|
||||||
|
const res = await searchMaterialBase(query)
|
||||||
|
if (res.code === 200) {
|
||||||
|
materialOptions.value = res.data
|
||||||
|
} else {
|
||||||
|
materialOptions.value = []
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
materialOptions.value = []
|
||||||
|
} finally {
|
||||||
|
searchLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onMaterialSelected = (val: number) => {
|
||||||
|
const item = materialOptions.value.find(i => i.id === val)
|
||||||
|
if (item) {
|
||||||
|
form.material_name = item.name
|
||||||
|
form.spec_model = item.spec
|
||||||
|
form.category = item.category
|
||||||
|
form.unit = item.unit
|
||||||
|
form.material_type = item.type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 弹窗相关
|
// 弹窗相关
|
||||||
const dialogVisible = ref(false)
|
const dialogVisible = ref(false)
|
||||||
const dialogTitle = ref('')
|
const dialogTitle = ref('')
|
||||||
@ -216,6 +292,11 @@ const formRef = ref<FormInstance>()
|
|||||||
const form = reactive({
|
const form = reactive({
|
||||||
id: 0,
|
id: 0,
|
||||||
base_id: 0,
|
base_id: 0,
|
||||||
|
material_name: '',
|
||||||
|
spec_model: '',
|
||||||
|
category: '',
|
||||||
|
unit: '',
|
||||||
|
material_type: '',
|
||||||
sale_price: 0,
|
sale_price: 0,
|
||||||
provider_name: '',
|
provider_name: '',
|
||||||
description: ''
|
description: ''
|
||||||
@ -250,6 +331,11 @@ const handleEdit = (row: ServiceItem) => {
|
|||||||
Object.assign(form, {
|
Object.assign(form, {
|
||||||
id: row.id,
|
id: row.id,
|
||||||
base_id: row.base_id,
|
base_id: row.base_id,
|
||||||
|
material_name: row.material_name || '',
|
||||||
|
spec_model: row.spec_model || '',
|
||||||
|
category: row.category || '',
|
||||||
|
unit: row.unit || '',
|
||||||
|
material_type: row.material_type || '',
|
||||||
sale_price: row.sale_price,
|
sale_price: row.sale_price,
|
||||||
provider_name: row.provider_name,
|
provider_name: row.provider_name,
|
||||||
description: row.description
|
description: row.description
|
||||||
|
|||||||
Reference in New Issue
Block a user