董国庆
2026-06-17 1cd7726fdc4039651c6768b9b99b9131b9cb058e
更改bug
5个文件已修改
151 ■■■■■ 已修改文件
src/views/assetManagement/fleetManagement/components/StaffSelectModal.vue 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/businessOperations/operationWorkbench/components/FencePanel.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/businessOperations/operationWorkbench/map.vue 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/operations/taskOrder/taskOrderCenter/components/TableModal.vue 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/service/review/personnel/index.vue 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/assetManagement/fleetManagement/components/StaffSelectModal.vue
@@ -1,8 +1,9 @@
<script setup lang="tsx">
import type { DataTableColumns } from 'naive-ui'
import { NAvatar, NButton, NSelect, NSpace } from 'naive-ui'
import { NButton, NImage, NSelect, NSpace } from 'naive-ui'
import { useBoolean } from '@/hooks'
import { fetchOperationsUserList, fetchRoleList } from '@/service/api/fleet'
import defaultAvatarImg from '@/assets/public/avater.png'
interface StaffItem {
  id: number
@@ -53,6 +54,19 @@
const currentPage = ref(1)
const pageSize = ref(10)
function getAvatarUrl(avatar?: string) {
  if (!avatar)
    return ''
  try {
    const parsedAvatar = JSON.parse(avatar)
    return parsedAvatar?.url || ''
  }
  catch {
    return avatar
  }
}
// 表格列定义
const columns = computed<DataTableColumns<StaffItem>>(() => [
  {
@@ -65,9 +79,34 @@
    key: 'nickName',
    width: 200,
    render: (row) => {
      const avatarUrl = getAvatarUrl(row.avatar)
      return (
        <NSpace align="center" justify="flex-start">
          <NAvatar round size={32} src={row.avatar} fallback-src="https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/9bed493b-a6aa-4ef6-ac10-7f67f5c6adc5.png" style={{ backgroundColor: '#d0d0d0' }}></NAvatar>
          {avatarUrl
            ? (
                <NImage
                  src={avatarUrl}
                  width={32}
                  height={32}
                  objectFit="cover"
                  imgProps={{ style: { borderRadius: '50%' } }}
                  previewDisabled={false}
                  fallbackSrc="https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/9bed493b-a6aa-4ef6-ac10-7f67f5c6adc5.png"
                />
              )
            : (
                <div
                  class="flex justify-center items-center"
                  style={{ width: '32px', height: '32px', borderRadius: '50%', backgroundColor: '#F6F7FA', flexShrink: 0 }}
                >
                  <NImage
                    src={defaultAvatarImg}
                    width={17}
                    height={21}
                    previewDisabled
                  />
                </div>
              )}
          <span>{row.nickName}</span>
        </NSpace>
      )
src/views/businessOperations/operationWorkbench/components/FencePanel.vue
@@ -511,7 +511,7 @@
                :checked-value="1"
                :unchecked-value="2"
                :disabled="isAreaStatusSwitchDisabled"
                class="text-13px"
                class="text-13px flex-shrink-0"
              >
                <template #checked> 启用 </template>
                <template #unchecked> 停用 </template>
@@ -1601,6 +1601,9 @@
  position: absolute;
  inset: 0;
}
.flex-shrink-0 {
  flex-shrink: 0;
}
:deep(.n-date-picker) {
  height: 100%;
src/views/businessOperations/operationWorkbench/map.vue
@@ -10,6 +10,7 @@
  ref,
  shallowRef,
  watch,
  h,
} from "vue";
import { onBeforeRouteLeave, useRoute, useRouter } from "vue-router";
import {
@@ -1098,18 +1099,38 @@
  };
});
/**
 * 根据围栏修改的影响范围,生成提交时的二次确认提示文案
 * @param disabledPointCount - 因移出围栏而将被停用的点位数量
 * @returns 拼接好的确认提示文案(返回一个渲染函数以支持高亮)。如果没有任何移出影响,则返回空字符串
 */
function buildFenceSubmitConfirmMessage(disabledPointCount = 0) {
  // 1. 从状态中获取本次修改将要移出的【点位数量】和【场站数量】
  const pointCount = fenceImpactDeltaSummary.value.remove.pointCount;
  const stationCount = fenceImpactDeltaSummary.value.remove.stationCount;
  const segments: string[] = [];
  if (pointCount && stationCount)
    segments.push(`将移出${pointCount}个点位、${stationCount}个场站`);
  else if (pointCount) segments.push(`将移出${pointCount}个点位`);
  else if (stationCount) segments.push(`将移出${stationCount}个场站`);
  if (disabledPointCount > 0)
    segments.push(`其中${disabledPointCount}个点位会被停用`);
  if (!segments.length) return "";
  return `确认提交吗?本次修改${segments.join(",")}。`;
  // 2. 如果没有任何点位和场站被移出,直接返回空字符串
  if (!pointCount && !stationCount) return "";
  // 3. 返回一个渲染函数,使用 h 函数生成虚拟 DOM 以支持文案的高亮显示
  return () => {
    const parts = [];
    parts.push('因围栏调整,有 ');
    // 拼接点位和场站高亮片段
    if (pointCount > 0) {
      parts.push(h('span', { style: 'color: #0068FF;' }, `${pointCount}个点位`));
    }
    if (pointCount > 0 && stationCount > 0) {
      parts.push('、');
    }
    if (stationCount > 0) {
      parts.push(h('span', { style: 'color: #0068FF;' }, `${stationCount}个场站`));
    }
    parts.push(' 将变更为“已停用”,确认发布本次修改?');
    return h('span', null, parts);
  };
}
const fenceOutOfRangePointList = computed(() => {
@@ -4322,7 +4343,7 @@
function openConfirmDialog(
  title: string,
  content = "",
  content: string | (() => any) = "",
  options?: {
    positiveText?: string;
    negativeText?: string;
src/views/operations/taskOrder/taskOrderCenter/components/TableModal.vue
@@ -74,6 +74,22 @@
const userList = ref<any[]>([]);
const userOptions = computed(() =>
  userList.value.map(item => ({
    label: item.nickName || "-",
    value: item.id,
    searchText: `${item.nickName || ""}`.toLowerCase(),
  })),
);
function handleUserFilter(pattern: string, option: any) {
  const keyword = pattern.trim().toLowerCase();
  if (!keyword)
    return true;
  return option.searchText?.includes(keyword) ?? false;
}
const getUserList = async () => {
  const res = await getOperationsUserListNoPage();
  if (res.code === 200) {
@@ -103,9 +119,11 @@
      <n-form-item label="选择处理人" path="handlerUserId">
        <n-select
          v-model:value="formModel.handlerUserId"
          :options="userList"
          value-field="id"
          label-field="nickName"
          :options="userOptions"
          filterable
          clearable
          placeholder="请输入姓名搜索"
          :filter="handleUserFilter"
          @update:show="val => isUserSelectOpen = val"
        >
          <template #arrow>
src/views/service/review/personnel/index.vue
@@ -1,7 +1,7 @@
<script setup lang="tsx">
import { computed, onMounted, ref, watch } from 'vue'
import type { DataTableColumns } from 'naive-ui'
import { NButton, NSpace, NTag, NTooltip } from 'naive-ui'
import { NButton, NImage, NSpace, NTag, NTooltip } from 'naive-ui'
import { useBoolean } from '@/hooks'
import OperationLogModal from '@/components/custom/OperationLogModal.vue'
import {
@@ -51,6 +51,19 @@
  3: 'error',
}
function getAvatarUrl(avatar?: string) {
  if (!avatar)
    return ''
  try {
    const parsedAvatar = JSON.parse(avatar)
    return parsedAvatar?.url || ''
  }
  catch {
    return avatar
  }
}
const columns: DataTableColumns<any> = [
  {
    type: 'selection',
@@ -68,12 +81,29 @@
    width: 150,
    resizable: true,
    render: (row) => {
      const avatarUrl = getAvatarUrl(row.avatar)
      return (
        <div class="flex items-center gap-2">
          {row.avatar && <img src={JSON.parse(row.avatar).url} alt="头像" class="w-24px h-24px rounded-full" onError={(e: any) => { e.target.src = 'https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/9bed493b-a6aa-4ef6-ac10-7f67f5c6adc5.png' }} />}
          {!row.avatar && (
          {avatarUrl
            ? (
                <NImage
                  src={avatarUrl}
                  width={24}
                  height={24}
                  objectFit="cover"
                  imgProps={{ style: { borderRadius: '50%' } }}
                  previewDisabled={false}
                  fallbackSrc="https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/9bed493b-a6aa-4ef6-ac10-7f67f5c6adc5.png"
                />
              )
            : (
            <div class="w-24px h-24px rounded-full flex justify-center" style="background-color: #F6F7FA;">
              <img src={defaultAvatarImg} class="w-17px h-21px" />
              <NImage
                src={defaultAvatarImg}
                width={17}
                height={21}
                previewDisabled
              />
            </div>
          )}
          <NTooltip trigger="hover" placement="top" max-width="500px">