11
This commit is contained in:
1 parent
8cc6972f1c
commit
5668acf964
5 files changed
+155
-52
No files matched your search
@@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<el-select v-model="state.selectedLabels" multiple filterable collapse-tags collapse-tags-tooltip
|
||||
:max-collapse-tags="props.maxCollapseTags" :placeholder="props.placeholder" :clearable="props.clearable"
|
||||
:disabled="props.disabled" style="width: 100%" @change="handleChange">
|
||||
<el-option v-for="item in capabilityOptions" :key="item.value" :label="item.label" :value="item.value">
|
||||
<div class="flex items-center justify-between gap-3">
|
||||
<span class="truncate">{{ item.label }}</span>
|
||||
<el-tag size="small" effect="plain">第{{ item.bit }}位</el-tag>
|
||||
</div>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="select-device-capability">
|
||||
import {
|
||||
DEVICE_CAPABILITY_LABELS,
|
||||
formatDeviceCapability,
|
||||
parseDeviceCapability,
|
||||
} from '/@/utils/dispose'
|
||||
|
||||
const emit = defineEmits(['change'])
|
||||
|
||||
const selectValue = defineModel<any>()
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
placeholder?: string
|
||||
disabled?: boolean
|
||||
clearable?: boolean
|
||||
outputFormat?: 'comma' | 'binary' | 'decimal' | 'labels'
|
||||
maxCollapseTags?: number
|
||||
}>(),
|
||||
{
|
||||
placeholder: '请选择通道能力',
|
||||
disabled: false,
|
||||
clearable: true,
|
||||
outputFormat: 'comma',
|
||||
maxCollapseTags: 3,
|
||||
},
|
||||
)
|
||||
|
||||
const capabilityOptions = DEVICE_CAPABILITY_LABELS.map((label, index) => ({
|
||||
label,
|
||||
value: label,
|
||||
bit: index + 1,
|
||||
}))
|
||||
|
||||
const state = reactive({
|
||||
selectedLabels: [] as string[],
|
||||
})
|
||||
|
||||
const normalizeToLabels = (value: unknown) => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.filter((item): item is string => typeof item === 'string' && DEVICE_CAPABILITY_LABELS.includes(item))
|
||||
}
|
||||
if (typeof value === 'number') {
|
||||
return parseDeviceCapability(`${value}`)
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
const trimmed = value.trim()
|
||||
if (!trimmed) return []
|
||||
if (/^[01,\s]+$/.test(trimmed) || /^\d+$/.test(trimmed)) {
|
||||
return parseDeviceCapability(trimmed)
|
||||
}
|
||||
return trimmed
|
||||
.split(/[、,,]/)
|
||||
.map((item) => item.trim())
|
||||
.filter((item) => DEVICE_CAPABILITY_LABELS.includes(item))
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
const formatOutputValue = (labels: string[]) => {
|
||||
if (props.outputFormat === 'labels') {
|
||||
return labels
|
||||
}
|
||||
return formatDeviceCapability(labels, props.outputFormat)
|
||||
}
|
||||
|
||||
const syncSelectedLabels = (value: unknown) => {
|
||||
state.selectedLabels = normalizeToLabels(value)
|
||||
}
|
||||
|
||||
const handleChange = (labels: string[]) => {
|
||||
const formattedValue = formatOutputValue(labels)
|
||||
selectValue.value = formattedValue
|
||||
emit('change', formattedValue)
|
||||
}
|
||||
|
||||
watch(
|
||||
selectValue,
|
||||
(newVal, oldVal) => {
|
||||
if (newVal === oldVal && state.selectedLabels.length) return
|
||||
syncSelectedLabels(newVal)
|
||||
},
|
||||
{ immediate: true, deep: true },
|
||||
)
|
||||
</script>
|
||||
@@ -28,6 +28,7 @@ import TagUserStatus from "/@/components/Tag/TagUserStatus.vue";
|
||||
|
||||
import SelectArea from "/@/components/Select/SelectArea.vue";
|
||||
import SelectDevice from "/@/components/Select/SelectDevice.vue";
|
||||
import SelectDeviceCapability from "/@/components/Select/SelectDeviceCapability.vue";
|
||||
import SelectDeviceGroup from "/@/components/Select/SelectDeviceGroup.vue";
|
||||
import SelectDuty from "/@/components/Select/SelectDuty.vue";
|
||||
import SelectDutyType from "/@/components/Select/SelectDutyType.vue";
|
||||
@@ -99,6 +100,7 @@ export default {
|
||||
|
||||
app.component("SelectArea", SelectArea);
|
||||
app.component("SelectDevice", SelectDevice);
|
||||
app.component("SelectDeviceCapability", SelectDeviceCapability);
|
||||
app.component("SelectDeviceGroup", SelectDeviceGroup);
|
||||
app.component("SelectDuty", SelectDuty);
|
||||
app.component("SelectDutyType", SelectDutyType);
|
||||
|
||||
+54
-36
@@ -61,42 +61,43 @@ export function timeDiffBySeconds(seconds: number | string) {
|
||||
* 3) 十进制字符串,例如 "12345";将自动转换为二进制位图
|
||||
* - 输出:返回启用能力对应的中文名称数组(仅包含位为 1 的能力)
|
||||
*/
|
||||
export const DEVICE_CAPABILITY_LABELS: string[] = [
|
||||
"智能报警",
|
||||
"鱼眼",
|
||||
"电动聚焦",
|
||||
"红外测温",
|
||||
"热度图统计",
|
||||
"过线统计",
|
||||
"区域人数统计",
|
||||
"人脸检测",
|
||||
"人员识别",
|
||||
"目标抓拍",
|
||||
"主从跟踪",
|
||||
"出入口抓拍",
|
||||
"AR",
|
||||
"多区域人数统计",
|
||||
"雷球联动",
|
||||
"行为分析",
|
||||
"云台控制",
|
||||
"保留位",
|
||||
"扬声器",
|
||||
"智能算法升级",
|
||||
"MAC采集",
|
||||
"自定义定时抓图",
|
||||
"人脸开门",
|
||||
"工装检测",
|
||||
"人脸质量检测",
|
||||
"人脸相似度比对",
|
||||
"客流定时订阅",
|
||||
"人脸分析",
|
||||
"AR后端打标",
|
||||
"AR广角180°",
|
||||
"AR广角360°",
|
||||
"废弃位",
|
||||
];
|
||||
|
||||
export function parseDeviceCapability(capability: string): string[] {
|
||||
if (!capability) return [];
|
||||
const labels: string[] = [
|
||||
"智能报警",
|
||||
"鱼眼",
|
||||
"电动聚焦",
|
||||
"红外测温",
|
||||
"热度图统计",
|
||||
"过线统计",
|
||||
"区域人数统计",
|
||||
"人脸检测",
|
||||
"人员识别",
|
||||
"目标抓拍",
|
||||
"主从跟踪",
|
||||
"出入口抓拍",
|
||||
"AR",
|
||||
"多区域人数统计",
|
||||
"雷球联动",
|
||||
"行为分析",
|
||||
"云台控制",
|
||||
"保留位",
|
||||
"扬声器",
|
||||
"智能算法升级",
|
||||
"MAC采集",
|
||||
"自定义定时抓图",
|
||||
"人脸开门",
|
||||
"工装检测",
|
||||
"人脸质量检测",
|
||||
"人脸相似度比对",
|
||||
"客流定时订阅",
|
||||
"人脸分析",
|
||||
"AR后端打标",
|
||||
"AR广角180°",
|
||||
"AR广角360°",
|
||||
"废弃位",
|
||||
];
|
||||
const trimmed = capability.trim();
|
||||
let getBitFromRight: (posFromRight: number) => number;
|
||||
if (trimmed.includes(",")) {
|
||||
@@ -123,8 +124,25 @@ export function parseDeviceCapability(capability: string): string[] {
|
||||
return [];
|
||||
}
|
||||
const result: string[] = [];
|
||||
for (let i = 1; i <= labels.length; i++) {
|
||||
if (getBitFromRight(i) === 1) result.push(labels[i - 1]);
|
||||
for (let i = 1; i <= DEVICE_CAPABILITY_LABELS.length; i++) {
|
||||
if (getBitFromRight(i) === 1) result.push(DEVICE_CAPABILITY_LABELS[i - 1]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function formatDeviceCapability(
|
||||
labels: string[],
|
||||
format: "comma" | "binary" | "decimal" = "comma"
|
||||
) {
|
||||
const bitList = DEVICE_CAPABILITY_LABELS.map((label) =>
|
||||
labels.includes(label) ? "1" : "0"
|
||||
);
|
||||
if (format === "binary") {
|
||||
return [...bitList].reverse().join("");
|
||||
}
|
||||
if (format === "decimal") {
|
||||
const binary = [...bitList].reverse().join("").replace(/^0+/, "");
|
||||
return binary ? BigInt(`0b${binary}`).toString(10) : "0";
|
||||
}
|
||||
return bitList.join(",");
|
||||
}
|
||||
@@ -36,7 +36,7 @@
|
||||
</el-col>
|
||||
<el-col :span="24" class="mb20">
|
||||
<el-form-item label="通道能力" prop="capability">
|
||||
<el-input v-model="form.capability" type="textarea" :rows="3" placeholder="请输入通道能力集" />
|
||||
<select-device-capability v-model="form.capability" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24" class="mb20">
|
||||
|
||||
@@ -17,26 +17,11 @@
|
||||
<el-input v-model="form.orgName" placeholder="请输入组织名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="唯一标识码" prop="orgSn">
|
||||
<el-input v-model="form.orgSn" placeholder="请输入唯一标识码" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="组织类型" prop="orgType">
|
||||
<dict-select disabled v-model="form.orgType" :options="dh_org_type" placeholder="请选择组织类型" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="状态" prop="stat">
|
||||
<el-input v-model="form.stat" placeholder="请输入状态" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="排序码" prop="sort">
|
||||
<el-input v-model="form.sort" placeholder="请输入排序码" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
|
||||
Reference in new issue
Block a user