ai-coding
2026-07-29 c26c68e3f9cdc75fa2815bc938071040d6bc0806
feat: 协议管理新增协议类型列;冻结文本编辑工具栏

Co-Authored-By: 王心悦 <wangxy84@xiaopeng.com>
1个文件已添加
5个文件已修改
104 ■■■■■ 已修改文件
src/components/custom/Editor/AiRichTextEditor/index.vue 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/service/api/operations.ts 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/userContent/contentCenter/agreementVersion.vue 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/userContent/contentCenter/components/AgreementListForm.vue 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/userContent/contentCenter/components/AgreementVersionModal.vue 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/userContent/contentCenter/constants/agreementCategory.ts 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/custom/Editor/AiRichTextEditor/index.vue
@@ -795,7 +795,7 @@
.ai-editor-host {
  width: 100%;
  min-height: v-bind(height);
  height: v-bind(height);
}
.ai-editor-count {
@@ -827,12 +827,14 @@
  overflow: hidden;
  border: 1px solid rgba(23, 31, 38, 0.15);
  box-sizing: border-box;
  min-height: 100%;
  height: v-bind(height);
  max-height: v-bind(height);
}
:deep(.aie-container aie-header) {
  background: #f4f6f8;
  border-bottom: 1px solid rgba(23, 31, 38, 0.15);
  flex-shrink: 0;
}
:deep(.aie-container aie-header > div) {
@@ -848,8 +850,8 @@
}
:deep(.aie-main) {
  flex: 1;
   min-height: v-bind(height);
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
}
src/service/api/operations.ts
@@ -11,6 +11,7 @@
  version?: string
  status?: number
  sort?: number
  agreementCategory?: number | null
}) {
  return request.Post<Service.ResponseResult<any>>('/operation/api/v1/agreement/saveLoginAgreement', data)
}
@@ -28,6 +29,7 @@
    updateBy: string
    updateTime: string
    version: string
    latestAgreementCategory: number | null
  }>>>(`/operation/api/v1/agreement/getLoginAgreementPageList/${type}`)
}
@@ -54,6 +56,7 @@
      updateBy: string
      updateTime: string
      version: string
      agreementCategory: number | null
    }>
    size: number
    total: number
@@ -77,6 +80,7 @@
    updateBy: string
    updateTime: string
    version: string
    agreementCategory: number | null
  }>>(`/operation/api/v1/agreement/loginAgreement/detail/${id}`)
}
src/views/userContent/contentCenter/agreementVersion.vue
@@ -7,6 +7,7 @@
import OperationLogModal from '@/components/custom/OperationLogModal.vue'
import AgreementVersionModal from './components/AgreementVersionModal.vue'
import type { AgreementVersionFormValue } from './components/AgreementVersionModal.vue'
import { getAgreementCategoryLabel } from './constants/agreementCategory'
import {
  copyLoginAgreement,
  disableLoginAgreement,
@@ -27,6 +28,7 @@
  sort: number
  isNew?: boolean
  status?: 0 | 1 | 2
  agreementCategory?: number | null
}
const route = useRoute()
@@ -145,6 +147,7 @@
      id: row.id,
      version: row.version,
      content: row.content,
      agreementCategory: row.agreementCategory ?? null,
    }
  }
  const res = await getLoginAgreementDetail(row.id)
@@ -181,6 +184,13 @@
    key: 'createTime',
    width: 200,
    resizable: true,
  },
  {
    title: '协议类型',
    key: 'agreementCategory',
    width: 140,
    resizable: true,
    render: (row: AgreementVersionRow) => getAgreementCategoryLabel(row.agreementCategory),
  },
  {
    title: '状态',
@@ -291,6 +301,7 @@
      sort: Number(item.sort || index + 1),
      isNew: false,
      status: [0, 1, 2].includes(Number(item.status)) ? Number(item.status) as 0 | 1 | 2 : undefined,
      agreementCategory: item.agreementCategory ?? null,
    }))
}
@@ -375,6 +386,7 @@
  openVersionModal('新增版本', {
    version,
    content: '',
    agreementCategory: null,
  })
}
@@ -391,6 +403,7 @@
    id: Number(detail.id),
    version: detail.version || row.version,
    content: detail.content || '',
    agreementCategory: detail.agreementCategory ?? null,
  })
}
@@ -411,6 +424,7 @@
    id: Number(detail.id),
    version: detail.version || row.version,
    content: detail.content || '',
    agreementCategory: detail.agreementCategory ?? null,
  }, true)
}
@@ -519,6 +533,7 @@
      type: agreementType.value,
      version: payload.version,
      status: 0,
      agreementCategory: payload.agreementCategory,
    })
    if (res?.code !== 200) {
      return
src/views/userContent/contentCenter/components/AgreementListForm.vue
@@ -13,6 +13,7 @@
  getLoginAgreementPageList,
  saveLoginAgreement,
} from "@/service/api/operations";
import { getAgreementCategoryLabel } from "../constants/agreementCategory";
import dayjs from "dayjs";
const props = defineProps<{
@@ -28,6 +29,7 @@
  updateTime: string;
  sort: number;
  version: string;
  agreementCategory?: number | null;
}
const router = useRouter();
@@ -67,6 +69,13 @@
    },
  },
  { title: titleLabel, resizable: true, key: "title" },
  {
    title: "协议类型",
    resizable: true,
    key: "agreementCategory",
    width: 140,
    render: (row: AgreementItem) => getAgreementCategoryLabel(row.agreementCategory),
  },
  { title: "启用中版本号", resizable: true, key: "version", width: 180 },
  { title: "创建人", resizable: true, key: "creator", width: 180 },
  {
@@ -124,6 +133,8 @@
      updateTime: item.updateTime || item.createTime || "",
      sort: Number(item.sort || 0),
      version: item.latestVersion || "-",
      // 协议列表展示的协议类型取"生效中版本"的协议类型,与启用中版本号同源
      agreementCategory: item.latestAgreementCategory ?? null,
    }));
}
src/views/userContent/contentCenter/components/AgreementVersionModal.vue
@@ -1,13 +1,15 @@
<script setup lang="ts">
import { computed, reactive, ref, watch } from 'vue'
import type { FormInst, FormRules } from 'naive-ui'
import { NButton, NForm, NFormItem, NInput, NModal, NSpace } from 'naive-ui'
import { NButton, NForm, NFormItem, NInput, NModal, NSelect, NSpace } from 'naive-ui'
import AiRichTextEditor from '@/components/custom/Editor/AiRichTextEditor/index.vue'
import { AGREEMENT_CATEGORY_OPTIONS } from '../constants/agreementCategory'
export interface AgreementVersionFormValue {
  id?: number
  version: string
  content: string
  agreementCategory?: number | null
}
const props = withDefaults(defineProps<{
@@ -32,6 +34,7 @@
const formModel = reactive<AgreementVersionFormValue>({
  version: '',
  content: '',
  agreementCategory: null,
})
const plainTextLength = computed(() => {
@@ -56,12 +59,21 @@
      trigger: ['blur', 'change', 'input'],
    },
  ],
  agreementCategory: [
    {
      required: true,
      type: 'number',
      message: '请选择协议类型',
      trigger: ['blur', 'change'],
    },
  ],
}
function resetForm() {
  formModel.id = props.rowData?.id
  formModel.version = props.rowData?.version || ''
  formModel.content = props.rowData?.content || ''
  formModel.agreementCategory = props.rowData?.agreementCategory ?? null
  formRef.value?.restoreValidation()
}
@@ -84,6 +96,7 @@
    id: formModel.id,
    version: formModel.version,
    content: formModel.content,
    agreementCategory: formModel.agreementCategory,
  })
}
@@ -112,9 +125,19 @@
      label-placement="top"
      require-mark-placement="left"
    >
      <NFormItem label="版本号" required>
        <NInput v-model:value="formModel.version" disabled placeholder="系统自动生成" />
      </NFormItem>
      <div class="form-row">
        <NFormItem label="版本号" required class="form-row-item">
          <NInput v-model:value="formModel.version" disabled placeholder="系统自动生成" />
        </NFormItem>
        <NFormItem label="协议类型" path="agreementCategory" required class="form-row-item">
          <NSelect
            v-model:value="formModel.agreementCategory"
            :options="AGREEMENT_CATEGORY_OPTIONS"
            :disabled="readonly"
            placeholder="请选择协议类型"
          />
        </NFormItem>
      </div>
      <NFormItem label="协议内容" path="content" required>
        <div class="rich-text-wrapper">
          <div class="editor-font-tip">
@@ -139,6 +162,16 @@
</template>
<style scoped lang="scss">
.form-row {
  display: flex;
  gap: 24px;
}
.form-row-item {
  flex: 1;
  min-width: 0;
}
.rich-text-wrapper {
  position: relative;
  width: 100%;
src/views/userContent/contentCenter/constants/agreementCategory.ts
New file
@@ -0,0 +1,23 @@
/** 登录协议-协议类型:主协议/子协议/共享协议 */
export const AGREEMENT_CATEGORY_MAIN = 1
export const AGREEMENT_CATEGORY_SUB = 2
export const AGREEMENT_CATEGORY_SHARED = 3
export const AGREEMENT_CATEGORY_OPTIONS = [
  { label: '主协议', value: AGREEMENT_CATEGORY_MAIN },
  { label: '子协议', value: AGREEMENT_CATEGORY_SUB },
  { label: '共享协议', value: AGREEMENT_CATEGORY_SHARED },
]
const AGREEMENT_CATEGORY_LABEL_MAP: Record<number, string> = {
  [AGREEMENT_CATEGORY_MAIN]: '主协议',
  [AGREEMENT_CATEGORY_SUB]: '子协议',
  [AGREEMENT_CATEGORY_SHARED]: '共享协议',
}
/** 存量协议未设置协议类型时返回空字符串,用于列表回显 */
export function getAgreementCategoryLabel(value?: number | null): string {
  if (value === null || value === undefined)
    return '-'
  return AGREEMENT_CATEGORY_LABEL_MAP[value] || '-'
}