feat:部门选择

This commit is contained in:
houjunxiang
2025-11-26 18:11:13 +08:00
parent 96cc747150
commit fcc04865f9
15 changed files with 344 additions and 83 deletions

View File

@@ -0,0 +1,196 @@
<template>
<view v-if="dialogStore.show" class="company-dept-dialog">
<view class="company-dept-dialog__mask" @tap="handleCancel" />
<view class="company-dept-dialog__panel">
<view class="company-dept-dialog__header">
<text class="company-dept-dialog__title">{{ dialogStore.title }}</text>
</view>
<view class="company-dept-dialog__body">
<!-- 公司选择 -->
<view class="company-dept-dialog__field">
<text class="company-dept-dialog__label">公司</text>
<uni-data-select
v-model="selectedCompanyModel"
:localdata="companyOptionsForSelect"
collection=""
field="companyName"
orderby=""
:clear-icon="false"
@change="onCompanyChangeUni"
/>
</view>
<!-- 部门选择 -->
<view class="company-dept-dialog__field">
<text class="company-dept-dialog__label">部门</text>
<uni-data-select
v-model="selectedDeptModel"
:localdata="deptOptionsForSelect"
collection=""
field="deptName"
orderby=""
:clear-icon="false"
@change="onDeptChangeUni"
/>
</view>
</view>
<view class="company-dept-dialog__footer">
<u-button @tap="handleCancel">取消</u-button>
<u-button type="primary" :disabled="!isConfirmEnabled" @tap="handleConfirm"> 确定 </u-button>
</view>
</view>
</view>
</template>
<script setup>
import { computed, ref, watch } from 'vue'
import { storeToRefs } from 'pinia'
import nx from '@/nx'
const dialogStore = nx.$store('company-dept')
const { companyList, selectedCompanyId, selectedDeptId } = storeToRefs(dialogStore)
const deptOptions = computed(() => dialogStore.getDeptsByCompanyId(selectedCompanyModel.value))
// 用于 uni-data-select 的格式:必须包含 value 和 text 字段
const companyOptionsForSelect = computed(() =>
companyList.value.map(item => ({
value: item.companyId,
text: item.companyName
}))
)
const deptOptionsForSelect = computed(() =>
deptOptions.value.map(item => ({
value: item.deptId,
text: item.deptName
}))
)
// 双向绑定模型uni-data-select 使用 value 绑定)
const selectedCompanyModel = ref(selectedCompanyId.value)
const selectedDeptModel = ref(selectedDeptId.value)
// 监听 store 变化,同步到 model应对外部触发更新
watch(
() => selectedCompanyId.value,
newVal => {
if (newVal !== selectedCompanyModel.value) {
selectedCompanyModel.value = newVal
}
}
)
watch(
() => selectedDeptId.value,
newVal => {
if (newVal !== selectedDeptModel.value) {
selectedDeptModel.value = newVal
}
}
)
// uni-data-select 的 change 回调
const onCompanyChangeUni = e => {
const companyId = e
if (companyId !== undefined && companyId !== null) {
dialogStore.setSelectedCompany(companyId)
// 重置部门选择
dialogStore.setSelectedDept('')
selectedDeptModel.value = ''
}
}
const onDeptChangeUni = e => {
const deptId = e
if (deptId !== undefined && deptId !== null) {
dialogStore.setSelectedDept(deptId)
}
}
// 按钮状态
const isConfirmEnabled = computed(() => !!dialogStore.selectedCompanyId && !!dialogStore.selectedDeptId)
// 操作
const handleCancel = () => {
dialogStore.cancel()
}
const handleConfirm = () => {
if (!isConfirmEnabled.value) return
dialogStore.confirm()
}
</script>
<style scoped lang="scss">
.company-dept-dialog {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 15000;
display: flex;
align-items: center;
justify-content: center;
&__mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.45);
}
&__panel {
position: relative;
width: 45vw;
background: #ffffff;
border-radius: 12px;
padding: 24px 20px 16px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18);
}
@media (max-width: 700px) {
&__panel {
width: 70vw;
}
}
&__header {
margin-bottom: 20px;
}
&__title {
display: block;
font-size: 18px;
font-weight: 600;
color: #1f1f1f;
text-align: center;
line-height: 1.4;
}
&__body {
display: flex;
flex-direction: column;
gap: 16px;
}
&__field {
display: flex;
flex-direction: column;
gap: 8px;
}
&__label {
font-size: 14px;
color: #606266;
}
&__footer {
display: flex;
justify-content: space-between;
gap: 12px;
margin-top: 24px;
}
}
</style>

View File

@@ -0,0 +1,10 @@
<template>
<view>
<slot />
<company-dept-dialog />
</view>
</template>
<script setup></script>
<style lang="scss" scoped></style>

View File

@@ -1,7 +1,7 @@
// 在此不用配置接口前缀 // 在此不用配置接口前缀
const isDev = process.env.NODE_ENV === 'development' const isDev = process.env.NODE_ENV === 'development'
// const BaseUrl = isDev ? 'http://192.168.26.116:888/admin-api' : 'http://192.168.26.116:888/admin-api' const BaseUrl = isDev ? 'http://192.168.26.116:888/admin-api' : 'http://192.168.26.116:888/admin-api'
const BaseUrl = isDev ? 'http://192.168.26.163:48080/admin-api' : 'http://192.168.26.116:888/admin-api' // const BaseUrl = isDev ? 'http://192.168.26.163:48080/admin-api' : 'http://192.168.26.116:888/admin-api'
// //
// const BaseUrl = isDev ? 'http://localhost:9999' : '' // const BaseUrl = isDev ? 'http://localhost:9999' : ''
const upgradeBaseUrl = 'http://192.168.26.116:888' const upgradeBaseUrl = 'http://192.168.26.116:888'

View File

@@ -63,6 +63,7 @@ export default {
method: 'GET', method: 'GET',
params params
}), }),
//调拨归还执行 //调拨归还执行
execGiveback: data => execGiveback: data =>
request({ request({

View File

@@ -25,6 +25,11 @@ export const apiCrypto = {
export const clientSecret = ' 2E1TFEkR8YaOcLhp' export const clientSecret = ' 2E1TFEkR8YaOcLhp'
// 附件前缀 // 附件前缀
export const attachmentKey = 'lims_attachment' export const attachmentKey = 'lims_attachment'
// 公司部门重试请求头
export const COMPANY_DEPT_RETRY_HEADER = '__companyDeptRetried'
export const VISIT_COMPANY_STORAGE_KEY = 'visit-company-info'
export const VISIT_DEPT_STORAGE_KEY = 'visit-dept-info'
export default { export default {
apiPath, apiPath,
apiCrypto, apiCrypto,

View File

@@ -7,6 +7,7 @@ import Request from 'luch-request'
import { getBaseUrl, getTenantId } from '@/defaultBaseUrl' import { getBaseUrl, getTenantId } from '@/defaultBaseUrl'
import $store from '@/nx/store' import $store from '@/nx/store'
import qs from 'qs' import qs from 'qs'
import { COMPANY_DEPT_RETRY_HEADER, VISIT_COMPANY_STORAGE_KEY, VISIT_DEPT_STORAGE_KEY } from '@/nx/config'
const options = { const options = {
// 显示操作成功消息 默认不显示 // 显示操作成功消息 默认不显示
@@ -27,9 +28,6 @@ const options = {
isTransformResponse: true isTransformResponse: true
} }
const COMPANY_DEPT_RETRY_HEADER = '__companyDeptRetried'
const VISIT_COMPANY_STORAGE_KEY = 'visit-company-info'
const VISIT_DEPT_STORAGE_KEY = 'visit-dept-info'
// Loading全局实例 // Loading全局实例
let LoadingInstance = { let LoadingInstance = {
target: null, target: null,
@@ -99,27 +97,19 @@ http.interceptors.request.use(
config.header['Pragma'] = 'no-cache' config.header['Pragma'] = 'no-cache'
} }
let params = config.params || {} const visitCompanyId = getVisitCompanyId()
let data = config.data || false
// if (process.env.NODE_ENV == 'development') console.log('development--params', params)
// if (process.env.NODE_ENV == 'development') console.log('development--data', data)
// const visitCompanyId = getVisitCompanyId()
const visitCompanyId = '101'
if (visitCompanyId !== undefined && visitCompanyId !== null && visitCompanyId !== '') { if (visitCompanyId !== undefined && visitCompanyId !== null && visitCompanyId !== '') {
config.header['visit-company-id'] = visitCompanyId config.header['visit-company-id'] = visitCompanyId
// const visitCompanyName = getVisitCompanyName() const visitCompanyName = getVisitCompanyName()
const visitCompanyName = '"深圳总公司'
if (visitCompanyName !== undefined && visitCompanyName !== null) { if (visitCompanyName !== undefined && visitCompanyName !== null) {
config.header['visit-company-name'] = encodeURIComponent(visitCompanyName || '') config.header['visit-company-name'] = encodeURIComponent(visitCompanyName || '')
} }
} }
// const visitDeptId = getVisitDeptId() const visitDeptId = getVisitDeptId()
const visitDeptId = '103'
if (visitDeptId !== undefined && visitDeptId !== null && visitDeptId !== '') { if (visitDeptId !== undefined && visitDeptId !== null && visitDeptId !== '') {
config.header['visit-dept-id'] = visitDeptId config.header['visit-dept-id'] = visitDeptId
// const visitDeptName = getVisitDeptName() const visitDeptName = getVisitDeptName()
const visitDeptName = '研发部门'
if (visitDeptName !== undefined && visitDeptName !== null) { if (visitDeptName !== undefined && visitDeptName !== null) {
config.header['visit-dept-name'] = encodeURIComponent(visitDeptName || '') config.header['visit-dept-name'] = encodeURIComponent(visitDeptName || '')
} }
@@ -153,7 +143,6 @@ http.interceptors.response.use(
// 统一处理【公司/部门二次选择】:参考 PC 端逻辑,自动补全或提示选择后重试 // 统一处理【公司/部门二次选择】:参考 PC 端逻辑,自动补全或提示选择后重试
if (code === 400 && Array.isArray(data)) { if (code === 400 && Array.isArray(data)) {
debugger
const companyDeptList = data const companyDeptList = data
const config = response.config const config = response.config
config.header = config.header || {} config.header = config.header || {}
@@ -161,7 +150,7 @@ http.interceptors.response.use(
const item = companyDeptList[0] const item = companyDeptList[0]
if (!config.header[COMPANY_DEPT_RETRY_HEADER]) { if (!config.header[COMPANY_DEPT_RETRY_HEADER]) {
applyCompanyDeptSelection(item, config) applyCompanyDeptSelection(item, config)
return request(config) return http.request(config)
} }
uni.showToast({ uni.showToast({
title: '公司/部门信息缺失,且自动补全失败,请联系管理员', title: '公司/部门信息缺失,且自动补全失败,请联系管理员',
@@ -187,7 +176,7 @@ http.interceptors.response.use(
}, },
config config
) )
resolve(request(config)) resolve(http.request(config))
}, },
onCancel: () => { onCancel: () => {
uni.showToast({ uni.showToast({

View File

@@ -1,4 +1,4 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia'
const defaultState = () => ({ const defaultState = () => ({
show: false, show: false,
@@ -7,60 +7,69 @@ const defaultState = () => ({
selectedCompanyId: null, selectedCompanyId: null,
selectedDeptId: null, selectedDeptId: null,
onConfirm: null, onConfirm: null,
onCancel: null, onCancel: null
}); })
const companyDeptStore = defineStore({ const companyDeptStore = defineStore({
id: 'company-dept', id: 'company-dept',
state: defaultState, state: defaultState,
actions: { actions: {
open({ companyList = [], onConfirm = null, onCancel = null, defaultCompanyId = null, defaultDeptId = null, title = null }) { open({
this.companyList = companyList; companyList = [],
this.onConfirm = onConfirm; onConfirm = null,
this.onCancel = onCancel; onCancel = null,
this.title = title || '请选择当前业务办理归属的公司部门信息'; defaultCompanyId = null,
this.show = true; defaultDeptId = null,
this.selectedCompanyId = defaultCompanyId; title = null
this.selectedDeptId = defaultDeptId; }) {
this.companyList = companyList
this.onConfirm = onConfirm
this.onCancel = onCancel
this.title = title || '请选择当前业务办理归属的公司部门信息'
this.show = true
this.selectedCompanyId = defaultCompanyId
this.selectedDeptId = defaultDeptId
if (!this.selectedCompanyId && this.companyList.length > 0) { if (!this.selectedCompanyId && this.companyList.length > 0) {
this.selectedCompanyId = this.companyList[0].companyId; this.selectedCompanyId = this.companyList[0].companyId
} }
if (!this.selectedDeptId) { if (!this.selectedDeptId) {
const depts = this.getDeptsByCompanyId(this.selectedCompanyId); const depts = this.getDeptsByCompanyId(this.selectedCompanyId)
this.selectedDeptId = depts.length > 0 ? depts[0].deptId : null; this.selectedDeptId = depts.length > 0 ? depts[0].deptId : null
} }
}, },
close() { close() {
Object.assign(this, defaultState()); this.show = false
}, },
getDeptsByCompanyId(companyId) { getDeptsByCompanyId(companyId) {
const company = this.companyList.find((item) => item.companyId === companyId); const company = this.companyList.find(item => item.companyId === companyId)
return company?.depts || []; return company?.depts || []
}, },
setSelectedCompany(companyId) { setSelectedCompany(companyId) {
this.selectedCompanyId = companyId; console.log(companyId)
const depts = this.getDeptsByCompanyId(companyId);
const currentDeptIds = depts.map((dept) => dept.deptId); this.selectedCompanyId = companyId
const depts = this.getDeptsByCompanyId(companyId)
const currentDeptIds = depts.map(dept => dept.deptId)
if (!currentDeptIds.includes(this.selectedDeptId)) { if (!currentDeptIds.includes(this.selectedDeptId)) {
this.selectedDeptId = depts.length > 0 ? depts[0].deptId : null; this.selectedDeptId = depts.length > 0 ? depts[0].deptId : null
} }
}, },
setSelectedDept(deptId) { setSelectedDept(deptId) {
this.selectedDeptId = deptId; this.selectedDeptId = deptId
}, },
confirm() { confirm() {
if (this.onConfirm) { if (this.onConfirm) {
this.onConfirm({ companyId: this.selectedCompanyId, deptId: this.selectedDeptId }); this.onConfirm({ companyId: this.selectedCompanyId, deptId: this.selectedDeptId })
} }
this.close(); this.close()
}, },
cancel() { cancel() {
if (this.onCancel) { if (this.onCancel) {
this.onCancel(); this.onCancel()
} }
this.close(); this.close()
}, }
}, }
}); })
export default companyDeptStore; export default companyDeptStore

View File

@@ -3,6 +3,7 @@ import userApi from '@/nx/api/user'
import { getSysParameterBizByName } from '@/nx/api/sys' import { getSysParameterBizByName } from '@/nx/api/sys'
import md5 from 'md5' import md5 from 'md5'
import nx from '@/nx' import nx from '@/nx'
import { COMPANY_DEPT_RETRY_HEADER, VISIT_COMPANY_STORAGE_KEY, VISIT_DEPT_STORAGE_KEY } from '@/nx/config'
// 默认用户信息 // 默认用户信息
const defaultUserInfo = { const defaultUserInfo = {
avatar: '', // 头像 avatar: '', // 头像
@@ -128,6 +129,10 @@ const user = defineStore({
this.roleMenus = [] this.roleMenus = []
uni.setStorageSync('roleMenus', []) uni.setStorageSync('roleMenus', [])
this.setToken() this.setToken()
// 清空部门信息
uni.removeStorageSync(COMPANY_DEPT_RETRY_HEADER)
uni.removeStorageSync(VISIT_COMPANY_STORAGE_KEY)
uni.removeStorageSync(VISIT_DEPT_STORAGE_KEY)
} }
} }
}) })

View File

@@ -57,7 +57,7 @@ const goTo = url => {
} }
// 生命周期 // 生命周期
onMounted(() => {})
// 动态设置 grid 列数 // 动态设置 grid 列数
const { gridCol } = useGridCol([400], [2, 3]) const { gridCol } = useGridCol([400], [2, 3])
</script> </script>

View File

@@ -96,7 +96,6 @@ import SampleDetailPopup from '@/components/sample/sample-detail-popup.vue'
import TaskItem from './components/task-item.vue' import TaskItem from './components/task-item.vue'
import nx from '@/nx' import nx from '@/nx'
import { useListData } from '@/nx/hooks/usePageListData' import { useListData } from '@/nx/hooks/usePageListData'
import { getDataSourceTypeShow } from '../common'
// 响应式数据 // 响应式数据
const scrollTop = ref(0) const scrollTop = ref(0)
@@ -136,7 +135,8 @@ const showSampleDetail = (id, index) => {
} }
const searchParams = computed(() => ({ const searchParams = computed(() => ({
taskAssignStatus: 'submitted', taskAssignStatus: 'submitted',
taskAssayStatus: 'submitted' taskAssayStatus: 'submitted',
assayOperator: userInfo.value.nickname
})) }))
const { listData, scrollToLower, loadStatus, getInitData } = useListData({ const { listData, scrollToLower, loadStatus, getInitData } = useListData({

View File

@@ -214,8 +214,8 @@ const getAssayTask = async () => {
rollbackContent.value = '' rollbackContent.value = ''
const param = { const param = {
taskAssignStatus: 'submitted', taskAssignStatus: 'submitted',
taskAssayStatusList: ['not_start', 'saved'] taskAssayStatusList: ['not_start', 'saved'],
// assayOper: userInfo.value.nickname assayOperator: userInfo.value.nickname
} }
const res = await nx.$api.assayTask.getAssayTaskList(param) const res = await nx.$api.assayTask.getAssayTaskList(param)
if (res) { if (res) {

View File

@@ -7,6 +7,7 @@
</up-grid-item> </up-grid-item>
</up-grid> </up-grid>
</view> </view>
<company-dept-dialog />
</template> </template>
<script setup> <script setup>
import { reactive, ref, computed, onMounted } from 'vue' import { reactive, ref, computed, onMounted } from 'vue'
@@ -23,7 +24,9 @@ function goSystem(url) {
uni.setStorageSync('defaultModule', url) uni.setStorageSync('defaultModule', url)
uni.reLaunch({ url }) uni.reLaunch({ url })
} }
onMounted(async () => {
await nx.$api.assayTask.getAssayTaskPage()
})
const { gridCol } = useGridCol([400, 600], [2, 3, 4]) const { gridCol } = useGridCol([400, 600], [2, 3, 4])
</script> </script>

View File

@@ -1,14 +1,19 @@
<template> <template>
<u-popup :show="show" mode="right" @close="close" @open="open" closeable> <u-popup :show="show" mode="right" @close="close" @open="open" closeable>
<view style="width: 50vw" class="p20"> <view class="p20 cell-content">
<scroll-view scroll-y="true"> <scroll-view scroll-y="true">
<view class="x-f pb20 pt20"> <view class="x-f pb20 pt20">
<u-avatar src=""></u-avatar> <u-avatar src=""></u-avatar>
<view class="pl20">您好{{ userInfo.nickname }}</view> <view>
<view class="pl20">您好{{ userInfo.nickname }}</view>
<view class="pl20">{{ deptName }}</view>
</view>
</view> </view>
<u-cell-group> <u-cell-group>
<u-cell icon="grid-fill" title="公司部门选择" :is-link="true" @click="handleSelectCompany" />
<u-cell icon="grid-fill" title="模块选择" :is-link="true" @click="handleTo('/pages/index/index')" /> <u-cell icon="grid-fill" title="模块选择" :is-link="true" @click="handleTo('/pages/index/index')" />
<u-cell icon="order" title="打印设置" :isLink="true" @click="handleTo('/pages/setting/print')"></u-cell> <u-cell icon="order" title="打印设置" :isLink="true" @click="handleTo('/pages/setting/print')"></u-cell>
<u-cell icon="info-circle-fill" title="关于我们" :is-link="true" @click="handleTo('/pages/me/aboutMe')" /> <u-cell icon="info-circle-fill" title="关于我们" :is-link="true" @click="handleTo('/pages/me/aboutMe')" />
</u-cell-group> </u-cell-group>
@@ -28,11 +33,14 @@
@cancel="modalShow = false" @cancel="modalShow = false"
/> />
</u-popup> </u-popup>
<company-dept-dialog />
</template> </template>
<script setup> <script setup>
import { ref, computed } from 'vue' import { ref, computed, onMounted } from 'vue'
import { storeToRefs } from 'pinia'
import nx from '@/nx' import nx from '@/nx'
import { VISIT_COMPANY_STORAGE_KEY, VISIT_DEPT_STORAGE_KEY } from '@/nx/config'
// Props & Emits // Props & Emits
const props = defineProps({ const props = defineProps({
@@ -46,15 +54,40 @@ const emit = defineEmits(['update:show', 'open', 'close'])
// 响应式数据 // 响应式数据
const modalShow = ref(false) const modalShow = ref(false)
const dialogStore = nx.$store('company-dept')
const { companyList, selectedCompanyId, selectedDeptId } = storeToRefs(dialogStore)
// 计算属性 // 计算属性
const userInfo = computed(() => nx.$store('user').userInfo) const userInfo = computed(() => nx.$store('user').userInfo)
const deptName = computed(() => {
const selectedCompany = companyList.value.find(company => company.companyId === selectedCompanyId.value)
const selectedDept = selectedCompany?.depts.find(dept => dept.deptId === selectedDeptId.value)
return selectedDept?.deptName || ''
})
// 方法 // 方法
const handleTo = url => { const handleTo = url => {
nx.$router.go(url) nx.$router.go(url)
} }
const handleSelectCompany = () => {
dialogStore.open({
companyList: companyList.value,
defaultCompanyId: selectedCompanyId.value,
defaultDeptId: selectedDeptId.value,
onConfirm: ({ companyId, deptId }) => {
const selectedCompany = companyList.value.find(company => company.companyId === selectedCompanyId.value)
const selectedDept = selectedCompany?.depts.find(dept => dept.deptId === selectedDeptId.value)
uni.setStorageSync(VISIT_COMPANY_STORAGE_KEY, {
id: companyId,
name: selectedCompany?.companyName || ''
})
uni.setStorageSync(VISIT_DEPT_STORAGE_KEY, {
id: deptId,
name: selectedDept?.deptName || ''
})
}
})
}
const handleLoginOut = () => { const handleLoginOut = () => {
modalShow.value = true modalShow.value = true
} }
@@ -77,6 +110,18 @@ const close = () => {
emit('close') emit('close')
emit('update:show', false) emit('update:show', false)
} }
onMounted(async () => {
await nx.$api.assayTask.getAssayTaskPage()
})
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped>
.cell-content {
width: 50vw;
}
@media (max-width: 700px) {
.cell-content {
width: 70vw;
}
}
</style>

View File

@@ -1,6 +1,6 @@
<template> <template>
<view class="container"> <view class="container">
<view class="x-f pb20 pt20"> <!-- <view class="x-f pb20 pt20">
<u-avatar src=""></u-avatar> <view class="user-name"><span>您好</span>{{ userInfo.realname }}</view> <u-avatar src=""></u-avatar> <view class="user-name"><span>您好</span>{{ userInfo.realname }}</view>
</view> </view>
<u-cell-group> <u-cell-group>
@@ -9,7 +9,7 @@
<u-cell icon="info-circle-fill" title="关于我们" :isLink="true" @click="handleTo('/pages/me/aboutMe')"></u-cell> <u-cell icon="info-circle-fill" title="关于我们" :isLink="true" @click="handleTo('/pages/me/aboutMe')"></u-cell>
</u-cell-group> </u-cell-group>
<u-button class="mt40" type="warning" :plain="true" text="退出当前账号" @click="handleLoginOut"></u-button> <u-button class="mt40" type="warning" :plain="true" text="退出当前账号" @click="handleLoginOut"></u-button>
<my-tabBar :currentTab="1" /> <my-tabBar :currentTab="1" /> -->
</view> </view>
</template> </template>
<script setup> <script setup>

View File

@@ -28,13 +28,17 @@
<view <view
>样品名称<text class="black">{{ item.sampleName }}</text></view >样品名称<text class="black">{{ item.sampleName }}</text></view
> >
<view>调拨人<text class="black">{{}}</text></view> <view
>调拨人<text class="black">{{ item.borrowUser }}</text></view
>
</view> </view>
<view class="x-bc"> <view class="x-bc">
<view <view
>样品编号<text class="black">{{ item.sampleReturnCode }}</text></view >样品编号<text class="black">{{ item.sampleReturnCode }}</text></view
> >
<view>调拨时间<text class="black">{{}}</text></view> <view
>调拨时间<text class="black">{{ nx.$dayjs(item.borrowTime).format('YYYY-MM-DD HH:mm:ss') }}</text></view
>
</view> </view>
<view class="mt4" <view class="mt4"
>归库编码<text class="black">{{ item.sampleReturnCode }}</text></view >归库编码<text class="black">{{ item.sampleReturnCode }}</text></view
@@ -89,25 +93,17 @@ onShow(() => {
async function getSampleList() { async function getSampleList() {
if (sampleCode.value === '') return if (sampleCode.value === '') return
let params = { let params = {
pageSize: 999,
pageNo: 1,
returnStatus: 'completed',
dispatchStatus: '1',
sampleReturnCode: sampleCode.value sampleReturnCode: sampleCode.value
} }
const { list } = await nx.$api.sampleWarehouse.queryReturnToStockSample(params) const data = await nx.$api.sampleWarehouse.searchBySampleCode(params)
if (list.length === 0) {
return uni.showToast({ title: '未查询到该样品信息', icon: 'none' })
}
const existingCodes = new Set(sampleList.value.map(item => item.id)) // 假设唯一标识是 `code`
const newItems = list.filter(item => !existingCodes.has(item.id))
if (newItems.length === 0) { const existingCodes = new Set(sampleList.value.map(item => item.id))
if (existingCodes.has(data.id)) {
return uni.showToast({ title: '该样品已存在,无需重复添加', icon: 'none' }) return uni.showToast({ title: '该样品已存在,无需重复添加', icon: 'none' })
} }
sampleList.value.push(...newItems) sampleList.value.push(data)
} }
async function handleSubmit() { async function handleSubmit() {
if (givebackUserId.value === '') { if (givebackUserId.value === '') {
@@ -117,12 +113,14 @@ async function handleSubmit() {
}) })
} }
btnLoading.value = true btnLoading.value = true
const givebackUser = range.value.find(item => item.value === givebackUserId.value)?.nickname const givebackUser = range.value.find(item => item.value === givebackUserId.value)?.text
await nx.$api.sampleWarehouse await nx.$api.sampleWarehouse
.execSampleDispatch({ .execGiveback({
detailIds: sampleList.value.map(item => item.id), detailIds: sampleList.value.map(item => item.id).join(','),
givebackUserId: givebackUserId.value, givebackUserId: givebackUserId.value,
givebackUser givebackUser,
warehouseUser: userInfo.value.nickname,
warehouseUserId: userInfo.value.id
}) })
.finally(() => { .finally(() => {
btnLoading.value = false btnLoading.value = false