|
|
|
|
@ -108,16 +108,24 @@
|
|
|
|
|
<u-icon name="scan" size="18" color="#1f4b79"></u-icon>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<picker :range="deviceLabels" :value="deviceIndex" :disabled="readonlyBase" @change="onDeviceChange">
|
|
|
|
|
<view :class="['picker-field', !formData.deviceId ? 'is-placeholder' : '']">{{ selectedDeviceLabel }}</view>
|
|
|
|
|
</picker>
|
|
|
|
|
<view
|
|
|
|
|
:class="['picker-field', !formData.deviceId ? 'is-placeholder' : '', readonlyBase ? 'is-disabled' : '']"
|
|
|
|
|
@click="openDevicePicker"
|
|
|
|
|
>
|
|
|
|
|
<text class="picker-field-text">{{ selectedDeviceLabel }}</text>
|
|
|
|
|
<u-icon v-if="!readonlyBase" name="arrow-down" size="16" color="#64748b"></u-icon>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view v-if="showComponentSelect" class="form-item">
|
|
|
|
|
<text class="form-label required">{{ t('equipmentMaintenance.component') }}</text>
|
|
|
|
|
<picker :range="componentLabels" :value="componentIndex" :disabled="readonlyBase" @change="onComponentChange">
|
|
|
|
|
<view :class="['picker-field', !formData.componentId ? 'is-placeholder' : '']">{{ selectedComponentLabel }}</view>
|
|
|
|
|
</picker>
|
|
|
|
|
<view
|
|
|
|
|
:class="['picker-field', !formData.componentId ? 'is-placeholder' : '', readonlyBase ? 'is-disabled' : '']"
|
|
|
|
|
@click="openComponentPicker"
|
|
|
|
|
>
|
|
|
|
|
<text class="picker-field-text">{{ selectedComponentLabel }}</text>
|
|
|
|
|
<u-icon v-if="!readonlyBase" name="arrow-down" size="16" color="#64748b"></u-icon>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
@ -232,6 +240,86 @@
|
|
|
|
|
<view class="footer-btn cancel" @click="goBack">{{ t('dashboard.back') }}</view>
|
|
|
|
|
<view v-if="!isReadonly" class="footer-btn confirm" @click="submitForm">{{ submitButtonText }}</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<uni-popup ref="devicePickerRef" type="bottom">
|
|
|
|
|
<view class="device-picker-popup">
|
|
|
|
|
<view class="device-picker-header">
|
|
|
|
|
<text class="device-picker-title">{{ t('equipmentMaintenance.placeholderDevice') }}</text>
|
|
|
|
|
<text class="device-picker-close" @click="closeDevicePicker">×</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="device-picker-search">
|
|
|
|
|
<view class="device-search-box">
|
|
|
|
|
<u-icon name="search" size="17" color="#94a3b8"></u-icon>
|
|
|
|
|
<input
|
|
|
|
|
v-model="deviceSearchKeyword"
|
|
|
|
|
class="device-search-input"
|
|
|
|
|
type="text"
|
|
|
|
|
confirm-type="search"
|
|
|
|
|
:placeholder="t('equipmentLedger.placeholderDeviceCode') + ' / ' + t('equipmentLedger.placeholderDeviceName')"
|
|
|
|
|
/>
|
|
|
|
|
<text v-if="deviceSearchKeyword" class="device-search-clear" @click="clearDeviceSearch">×</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<scroll-view scroll-y class="device-picker-scroll">
|
|
|
|
|
<view
|
|
|
|
|
v-for="item in filteredDeviceOptions"
|
|
|
|
|
:key="String(item.value)"
|
|
|
|
|
:class="['device-picker-item', String(item.value) === String(formData.deviceId || '') ? 'is-selected' : '']"
|
|
|
|
|
@click="selectDeviceOption(item)"
|
|
|
|
|
>
|
|
|
|
|
<view class="device-item-main">
|
|
|
|
|
<view class="device-item-title">
|
|
|
|
|
<text class="device-item-code">{{ item.raw?.deviceCode || String(item.value) }}</text>
|
|
|
|
|
<text class="device-item-name">{{ item.raw?.deviceName || '-' }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view v-if="deviceMetaText(item)" class="device-item-meta">{{ deviceMetaText(item) }}</view>
|
|
|
|
|
</view>
|
|
|
|
|
<u-icon v-if="String(item.value) === String(formData.deviceId || '')" name="checkmark" size="18" color="#1f4b79"></u-icon>
|
|
|
|
|
</view>
|
|
|
|
|
<view v-if="!filteredDeviceOptions.length" class="device-picker-empty">{{ t('equipmentMaintenance.deviceNotFound') }}</view>
|
|
|
|
|
</scroll-view>
|
|
|
|
|
</view>
|
|
|
|
|
</uni-popup>
|
|
|
|
|
|
|
|
|
|
<uni-popup ref="componentPickerRef" type="bottom">
|
|
|
|
|
<view class="device-picker-popup">
|
|
|
|
|
<view class="device-picker-header">
|
|
|
|
|
<text class="device-picker-title">{{ t('equipmentMaintenance.placeholderComponent') }}</text>
|
|
|
|
|
<text class="device-picker-close" @click="closeComponentPicker">×</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="device-picker-search">
|
|
|
|
|
<view class="device-search-box">
|
|
|
|
|
<u-icon name="search" size="17" color="#94a3b8"></u-icon>
|
|
|
|
|
<input
|
|
|
|
|
v-model="componentSearchKeyword"
|
|
|
|
|
class="device-search-input"
|
|
|
|
|
type="text"
|
|
|
|
|
confirm-type="search"
|
|
|
|
|
:placeholder="t('criticalComponent.placeholderCode') + ' / ' + t('criticalComponent.placeholderName')"
|
|
|
|
|
/>
|
|
|
|
|
<text v-if="componentSearchKeyword" class="device-search-clear" @click="clearComponentSearch">×</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<scroll-view scroll-y class="device-picker-scroll">
|
|
|
|
|
<view
|
|
|
|
|
v-for="item in searchableComponentOptions"
|
|
|
|
|
:key="String(item.value)"
|
|
|
|
|
:class="['device-picker-item', String(item.value) === String(formData.componentId || '') ? 'is-selected' : '']"
|
|
|
|
|
@click="selectComponentOption(item)"
|
|
|
|
|
>
|
|
|
|
|
<view class="device-item-main">
|
|
|
|
|
<view class="device-item-title">
|
|
|
|
|
<text class="device-item-code">{{ item.raw?.code || item.raw?.componentCode || '-' }}</text>
|
|
|
|
|
<text class="device-item-name">{{ item.raw?.name || item.raw?.componentName || '-' }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view v-if="componentMetaText(item)" class="device-item-meta">{{ componentMetaText(item) }}</view>
|
|
|
|
|
</view>
|
|
|
|
|
<u-icon v-if="String(item.value) === String(formData.componentId || '')" name="checkmark" size="18" color="#1f4b79"></u-icon>
|
|
|
|
|
</view>
|
|
|
|
|
<view v-if="!searchableComponentOptions.length" class="device-picker-empty">{{ t('equipmentMaintenance.deviceNotFound') }}</view>
|
|
|
|
|
</scroll-view>
|
|
|
|
|
</view>
|
|
|
|
|
</uni-popup>
|
|
|
|
|
</view>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
@ -261,6 +349,10 @@ const users = ref([])
|
|
|
|
|
const deviceOptions = ref([])
|
|
|
|
|
const componentOptions = ref([])
|
|
|
|
|
const loading = ref(false)
|
|
|
|
|
const devicePickerRef = ref(null)
|
|
|
|
|
const deviceSearchKeyword = ref('')
|
|
|
|
|
const componentPickerRef = ref(null)
|
|
|
|
|
const componentSearchKeyword = ref('')
|
|
|
|
|
|
|
|
|
|
const formData = reactive({
|
|
|
|
|
id: undefined,
|
|
|
|
|
@ -275,9 +367,9 @@ const formData = reactive({
|
|
|
|
|
machineryBrand: '',
|
|
|
|
|
machinerySpec: '',
|
|
|
|
|
machineryTypeId: 1,
|
|
|
|
|
requireDate: '',
|
|
|
|
|
finishDate: '',
|
|
|
|
|
confirmDate: '',
|
|
|
|
|
requireDate: todayPickerDate(),
|
|
|
|
|
finishDate: todayPickerDate(),
|
|
|
|
|
confirmDate: todayPickerDate(),
|
|
|
|
|
repairStatus: '0',
|
|
|
|
|
repairResult: '0',
|
|
|
|
|
acceptedBy: '',
|
|
|
|
|
@ -318,7 +410,6 @@ const statusLabel = computed(() => {
|
|
|
|
|
return t('equipmentMaintenance.statusPending')
|
|
|
|
|
})
|
|
|
|
|
const userLabels = computed(() => users.value.map((item) => item.nickname || item.name || String(item.id || '')))
|
|
|
|
|
const deviceLabels = computed(() => deviceOptions.value.map((item) => item.label))
|
|
|
|
|
const faultLevelOptions = computed(() => {
|
|
|
|
|
const dicts = dictStore.getDict(DICT_TYPE.FAILURE_LEVEL) || []
|
|
|
|
|
return dicts
|
|
|
|
|
@ -333,14 +424,32 @@ const confirmByIndex = computed(() => findUserIndex(formData.confirmBy))
|
|
|
|
|
const acceptedByLabel = computed(() => resolveUserLabel(formData.acceptedBy, t('equipmentMaintenance.placeholderAcceptedBy')))
|
|
|
|
|
const confirmByLabel = computed(() => resolveUserLabel(formData.confirmBy, t('equipmentMaintenance.placeholderConfirmBy')))
|
|
|
|
|
const showComponentSelect = computed(() => Number(formData.machineryTypeId || 1) === 2)
|
|
|
|
|
const deviceIndex = computed(() => {
|
|
|
|
|
const index = deviceOptions.value.findIndex((item) => String(item.value) === String(formData.deviceId || ''))
|
|
|
|
|
return index >= 0 ? index : 0
|
|
|
|
|
})
|
|
|
|
|
const selectedDeviceLabel = computed(() => {
|
|
|
|
|
const current = deviceOptions.value.find((item) => String(item.value) === String(formData.deviceId || ''))
|
|
|
|
|
return current?.label || t('equipmentMaintenance.placeholderDevice')
|
|
|
|
|
})
|
|
|
|
|
const filteredDeviceOptions = computed(() => {
|
|
|
|
|
const keyword = deviceSearchKeyword.value.trim().toLowerCase()
|
|
|
|
|
if (!keyword) return deviceOptions.value
|
|
|
|
|
const keywordId = extractEquipmentKeywordId(keyword)
|
|
|
|
|
return deviceOptions.value.filter((item) => {
|
|
|
|
|
const raw = item.raw || {}
|
|
|
|
|
const fields = [
|
|
|
|
|
item.label,
|
|
|
|
|
item.value,
|
|
|
|
|
raw.id,
|
|
|
|
|
raw.deviceId,
|
|
|
|
|
raw.machineryId,
|
|
|
|
|
raw.machineryid,
|
|
|
|
|
raw.deviceCode,
|
|
|
|
|
raw.deviceName,
|
|
|
|
|
raw.deviceBrand,
|
|
|
|
|
raw.deviceSpec
|
|
|
|
|
]
|
|
|
|
|
return fields.some((field) => String(field || '').toLowerCase().includes(keyword))
|
|
|
|
|
|| (keywordId && matchesDeviceOptionId(item, keywordId))
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
const filteredComponentOptions = computed(() => {
|
|
|
|
|
const source = Array.isArray(componentOptions.value) ? componentOptions.value : []
|
|
|
|
|
const currentDeviceId = String(formData.deviceId || '').trim()
|
|
|
|
|
@ -348,10 +457,22 @@ const filteredComponentOptions = computed(() => {
|
|
|
|
|
const matched = source.filter((item) => matchesComponentDevice(item?.raw, currentDeviceId))
|
|
|
|
|
return matched.length ? matched : source
|
|
|
|
|
})
|
|
|
|
|
const componentLabels = computed(() => filteredComponentOptions.value.map((item) => item.label))
|
|
|
|
|
const componentIndex = computed(() => {
|
|
|
|
|
const index = filteredComponentOptions.value.findIndex((item) => String(item.value) === String(formData.componentId || ''))
|
|
|
|
|
return index >= 0 ? index : 0
|
|
|
|
|
const searchableComponentOptions = computed(() => {
|
|
|
|
|
const keyword = componentSearchKeyword.value.trim().toLowerCase()
|
|
|
|
|
if (!keyword) return filteredComponentOptions.value
|
|
|
|
|
return filteredComponentOptions.value.filter((item) => {
|
|
|
|
|
const raw = item.raw || {}
|
|
|
|
|
const fields = [
|
|
|
|
|
item.label,
|
|
|
|
|
raw.code,
|
|
|
|
|
raw.componentCode,
|
|
|
|
|
raw.name,
|
|
|
|
|
raw.componentName,
|
|
|
|
|
raw.deviceName,
|
|
|
|
|
raw.deviceCode
|
|
|
|
|
]
|
|
|
|
|
return fields.some((field) => String(field || '').toLowerCase().includes(keyword))
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
const selectedComponentLabel = computed(() => {
|
|
|
|
|
const current = filteredComponentOptions.value.find((item) => String(item.value) === String(formData.componentId || ''))
|
|
|
|
|
@ -433,9 +554,9 @@ async function fetchDetail(id) {
|
|
|
|
|
formData.machineryBrand = inputValue(detail?.machineryBrand)
|
|
|
|
|
formData.machinerySpec = inputValue(detail?.machinerySpec)
|
|
|
|
|
formData.machineryTypeId = Number(detail?.machineryTypeId || 1) || 1
|
|
|
|
|
formData.requireDate = formatPickerDate(detail?.requireDate)
|
|
|
|
|
formData.finishDate = formatPickerDate(detail?.finishDate)
|
|
|
|
|
formData.confirmDate = formatPickerDate(detail?.confirmDate)
|
|
|
|
|
formData.requireDate = formatPickerDate(detail?.requireDate) || todayPickerDate()
|
|
|
|
|
formData.finishDate = formatPickerDate(detail?.finishDate) || todayPickerDate()
|
|
|
|
|
formData.confirmDate = formatPickerDate(detail?.confirmDate) || todayPickerDate()
|
|
|
|
|
formData.repairStatus = normalizedRepairStatus
|
|
|
|
|
formData.repairResult = normalizedRepairStatus
|
|
|
|
|
formData.acceptedBy = normalizeUserId(detail?.acceptedBy)
|
|
|
|
|
@ -513,17 +634,61 @@ function onUserChange(field, event) {
|
|
|
|
|
formData[field] = current ? String(current.id) : ''
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onDeviceChange(event) {
|
|
|
|
|
const index = Number(event?.detail?.value || 0)
|
|
|
|
|
const current = deviceOptions.value[index]
|
|
|
|
|
if (!current) return
|
|
|
|
|
function openDevicePicker() {
|
|
|
|
|
if (readonlyBase.value) return
|
|
|
|
|
devicePickerRef.value?.open?.()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function closeDevicePicker() {
|
|
|
|
|
devicePickerRef.value?.close?.()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function clearDeviceSearch() {
|
|
|
|
|
deviceSearchKeyword.value = ''
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function selectDeviceOption(current) {
|
|
|
|
|
if (!current || readonlyBase.value) return
|
|
|
|
|
applyDeviceOption(current)
|
|
|
|
|
clearDeviceSearch()
|
|
|
|
|
closeDevicePicker()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onComponentChange(event) {
|
|
|
|
|
const index = Number(event?.detail?.value || 0)
|
|
|
|
|
const current = filteredComponentOptions.value[index]
|
|
|
|
|
formData.componentId = current ? current.value : undefined
|
|
|
|
|
function deviceMetaText(item) {
|
|
|
|
|
const raw = item?.raw || {}
|
|
|
|
|
return [raw.deviceBrand, raw.deviceSpec].map(inputValue).filter(Boolean).join(' / ')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function openComponentPicker() {
|
|
|
|
|
if (readonlyBase.value) return
|
|
|
|
|
componentPickerRef.value?.open?.()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function closeComponentPicker() {
|
|
|
|
|
componentPickerRef.value?.close?.()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function clearComponentSearch() {
|
|
|
|
|
componentSearchKeyword.value = ''
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function selectComponentOption(current) {
|
|
|
|
|
if (!current || readonlyBase.value) return
|
|
|
|
|
formData.componentId = current.value
|
|
|
|
|
clearComponentSearch()
|
|
|
|
|
closeComponentPicker()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function componentMetaText(item) {
|
|
|
|
|
const raw = item?.raw || {}
|
|
|
|
|
return [
|
|
|
|
|
raw.deviceName,
|
|
|
|
|
raw.deviceCode,
|
|
|
|
|
raw.spec,
|
|
|
|
|
raw.componentSpec,
|
|
|
|
|
raw.model,
|
|
|
|
|
raw.componentModel
|
|
|
|
|
].map(inputValue).filter(Boolean).join(' / ')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function selectMachineryType(value) {
|
|
|
|
|
@ -552,7 +717,7 @@ async function handleDeviceScan() {
|
|
|
|
|
uni.showToast({ title: t('equipmentMaintenance.scanEquipmentRequired'), icon: 'none' })
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
const matched = deviceOptions.value.find((item) => String(item.value) === String(scan.id))
|
|
|
|
|
const matched = deviceOptions.value.find((item) => matchesDeviceOptionId(item, scan.id))
|
|
|
|
|
if (!matched) {
|
|
|
|
|
uni.showToast({ title: t('equipmentMaintenance.deviceNotFound'), icon: 'none' })
|
|
|
|
|
return
|
|
|
|
|
@ -587,6 +752,28 @@ function parseEquipmentScanResult(result) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function extractEquipmentKeywordId(keyword) {
|
|
|
|
|
const match = String(keyword || '').trim().match(/-(\d+)$/)
|
|
|
|
|
return match ? match[1] : ''
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getDeviceOptionIds(item) {
|
|
|
|
|
const raw = item?.raw || {}
|
|
|
|
|
return [
|
|
|
|
|
item?.value,
|
|
|
|
|
raw.id,
|
|
|
|
|
raw.deviceId,
|
|
|
|
|
raw.machineryId,
|
|
|
|
|
raw.machineryid
|
|
|
|
|
].filter((value) => value !== undefined && value !== null && value !== '')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function matchesDeviceOptionId(item, id) {
|
|
|
|
|
const target = String(id || '').trim()
|
|
|
|
|
if (!target) return false
|
|
|
|
|
return getDeviceOptionIds(item).some((value) => String(value) === target)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function applyDeviceOption(current) {
|
|
|
|
|
formData.deviceId = current.value
|
|
|
|
|
formData.machineryId = current.value
|
|
|
|
|
@ -671,6 +858,10 @@ function datePickerValue(value) {
|
|
|
|
|
return value || formatPickerDate(Date.now())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function todayPickerDate() {
|
|
|
|
|
return formatPickerDate(Date.now())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function formatPickerDate(value) {
|
|
|
|
|
if (value === undefined || value === null || value === '') return ''
|
|
|
|
|
const date = parseDate(value)
|
|
|
|
|
@ -1002,6 +1193,23 @@ function goBack() {
|
|
|
|
|
color: #9ca3af;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.picker-field {
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
gap: 12rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.picker-field.is-disabled {
|
|
|
|
|
color: #64748b;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.picker-field-text {
|
|
|
|
|
flex: 1;
|
|
|
|
|
min-width: 0;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.code-row {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
@ -1161,4 +1369,146 @@ function goBack() {
|
|
|
|
|
background: #1f4b79;
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.device-picker-popup {
|
|
|
|
|
height: 72vh;
|
|
|
|
|
background: #ffffff;
|
|
|
|
|
border-radius: 22rpx 22rpx 0 0;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.device-picker-header {
|
|
|
|
|
position: relative;
|
|
|
|
|
height: 92rpx;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
border-bottom: 1rpx solid #eef2f7;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.device-picker-title {
|
|
|
|
|
font-size: 30rpx;
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
color: #111827;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.device-picker-close {
|
|
|
|
|
position: absolute;
|
|
|
|
|
right: 24rpx;
|
|
|
|
|
top: 14rpx;
|
|
|
|
|
width: 56rpx;
|
|
|
|
|
height: 56rpx;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
color: #64748b;
|
|
|
|
|
font-size: 42rpx;
|
|
|
|
|
line-height: 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.device-picker-search {
|
|
|
|
|
padding: 18rpx 24rpx 14rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.device-search-box {
|
|
|
|
|
height: 74rpx;
|
|
|
|
|
padding: 0 20rpx;
|
|
|
|
|
border-radius: 14rpx;
|
|
|
|
|
background: #f8fafc;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 12rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.device-search-input {
|
|
|
|
|
flex: 1;
|
|
|
|
|
height: 74rpx;
|
|
|
|
|
min-width: 0;
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
color: #111827;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.device-search-clear {
|
|
|
|
|
width: 44rpx;
|
|
|
|
|
height: 44rpx;
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
background: #e2e8f0;
|
|
|
|
|
color: #64748b;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
font-size: 30rpx;
|
|
|
|
|
line-height: 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.device-picker-scroll {
|
|
|
|
|
height: calc(72vh - 184rpx);
|
|
|
|
|
padding-bottom: calc(16rpx + env(safe-area-inset-bottom));
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.device-picker-item {
|
|
|
|
|
margin: 0 24rpx 14rpx;
|
|
|
|
|
padding: 20rpx;
|
|
|
|
|
border-radius: 16rpx;
|
|
|
|
|
background: #f8fafc;
|
|
|
|
|
border: 2rpx solid transparent;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
gap: 16rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.device-picker-item.is-selected {
|
|
|
|
|
background: #eef6ff;
|
|
|
|
|
border-color: #bfdbfe;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.device-item-main {
|
|
|
|
|
flex: 1;
|
|
|
|
|
min-width: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.device-item-title {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 12rpx;
|
|
|
|
|
min-width: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.device-item-code {
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
max-width: 52%;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
color: #111827;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.device-item-name {
|
|
|
|
|
min-width: 0;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
color: #334155;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.device-item-meta {
|
|
|
|
|
margin-top: 8rpx;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
color: #64748b;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.device-picker-empty {
|
|
|
|
|
padding: 72rpx 24rpx;
|
|
|
|
|
text-align: center;
|
|
|
|
|
color: #94a3b8;
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
|