@liujitcn/kratos-admin-system 0.0.32 → 0.0.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/dist/package/declarations/src/api/system/admin/v1/base_redact_output_policy.d.ts +19 -0
  2. package/dist/package/declarations/src/api/system/{base_redact_rule.d.ts → admin/v1/base_redact_rule.d.ts} +1 -1
  3. package/dist/package/declarations/src/api/system/admin/v1/base_redact_storage_policy.d.ts +19 -0
  4. package/dist/package/declarations/src/locales/generated.d.ts +292 -0
  5. package/dist/package/declarations/src/rpc/system/admin/v1/base_redact_output_policy.d.ts +135 -0
  6. package/dist/package/declarations/src/rpc/system/admin/v1/base_redact_rule.d.ts +0 -4
  7. package/dist/package/declarations/src/rpc/system/admin/v1/base_redact_storage_policy.d.ts +114 -0
  8. package/dist/package/src/api/system/admin/v1/base_redact_output_policy.ts +51 -0
  9. package/dist/package/src/api/system/{base_redact_rule.ts → admin/v1/base_redact_rule.ts} +1 -1
  10. package/dist/package/src/api/system/admin/v1/base_redact_storage_policy.ts +51 -0
  11. package/dist/package/src/locales/en-US.json +74 -1
  12. package/dist/package/src/locales/ja-JP.json +74 -1
  13. package/dist/package/src/locales/zh-CN.json +74 -1
  14. package/dist/package/src/locales/zh-TW.json +74 -1
  15. package/dist/package/src/rpc/base/v1/ai_message.ts +1 -1
  16. package/dist/package/src/rpc/base/v1/ai_session.ts +1 -1
  17. package/dist/package/src/rpc/base/v1/ai_tool.ts +1 -1
  18. package/dist/package/src/rpc/base/v1/config.ts +1 -1
  19. package/dist/package/src/rpc/base/v1/login.ts +1 -1
  20. package/dist/package/src/rpc/base/v1/notification.ts +1 -1
  21. package/dist/package/src/rpc/base/v1/oauth.ts +1 -1
  22. package/dist/package/src/rpc/base/v1/oauth_client.ts +1 -1
  23. package/dist/package/src/rpc/base/v1/sse.ts +1 -1
  24. package/dist/package/src/rpc/common/v1/analytics.ts +1 -1
  25. package/dist/package/src/rpc/common/v1/common.ts +1 -1
  26. package/dist/package/src/rpc/common/v1/enum.ts +1 -1
  27. package/dist/package/src/rpc/common/v1/types.ts +1 -1
  28. package/dist/package/src/rpc/google/protobuf/empty.ts +1 -1
  29. package/dist/package/src/rpc/google/protobuf/timestamp.ts +1 -1
  30. package/dist/package/src/rpc/system/admin/v1/auth.ts +1 -1
  31. package/dist/package/src/rpc/system/admin/v1/base_api.ts +1 -1
  32. package/dist/package/src/rpc/system/admin/v1/base_api_log.ts +1 -1
  33. package/dist/package/src/rpc/system/admin/v1/base_area.ts +1 -1
  34. package/dist/package/src/rpc/system/admin/v1/base_config.ts +1 -1
  35. package/dist/package/src/rpc/system/admin/v1/base_dashboard.ts +1 -1
  36. package/dist/package/src/rpc/system/admin/v1/base_data_access_log.ts +1 -1
  37. package/dist/package/src/rpc/system/admin/v1/base_dept.ts +1 -1
  38. package/dist/package/src/rpc/system/admin/v1/base_dict.ts +1 -1
  39. package/dist/package/src/rpc/system/admin/v1/base_dict_item.ts +1 -1
  40. package/dist/package/src/rpc/system/admin/v1/base_file.ts +1 -1
  41. package/dist/package/src/rpc/system/admin/v1/base_i18n.ts +1 -1
  42. package/dist/package/src/rpc/system/admin/v1/base_job.ts +1 -1
  43. package/dist/package/src/rpc/system/admin/v1/base_job_log.ts +1 -1
  44. package/dist/package/src/rpc/system/admin/v1/base_language.ts +1 -1
  45. package/dist/package/src/rpc/system/admin/v1/base_log.ts +1 -1
  46. package/dist/package/src/rpc/system/admin/v1/base_login_log.ts +1 -1
  47. package/dist/package/src/rpc/system/admin/v1/base_login_policy.ts +1 -1
  48. package/dist/package/src/rpc/system/admin/v1/base_menu.ts +1 -1
  49. package/dist/package/src/rpc/system/admin/v1/base_message.ts +1 -1
  50. package/dist/package/src/rpc/system/admin/v1/base_message_category.ts +1 -1
  51. package/dist/package/src/rpc/system/admin/v1/base_migration.ts +1 -1
  52. package/dist/package/src/rpc/system/admin/v1/base_operation_log.ts +1 -1
  53. package/dist/package/src/rpc/system/admin/v1/base_permission_log.ts +1 -1
  54. package/dist/package/src/rpc/system/admin/v1/base_policy_evaluation_log.ts +1 -1
  55. package/dist/package/src/rpc/system/admin/v1/base_post.ts +1 -1
  56. package/dist/package/src/rpc/system/admin/v1/base_redact_common.ts +1 -1
  57. package/dist/package/src/rpc/system/admin/v1/base_redact_output_policy.ts +157 -0
  58. package/dist/package/src/rpc/system/admin/v1/base_redact_rule.ts +1 -5
  59. package/dist/package/src/rpc/system/admin/v1/base_redact_storage_policy.ts +137 -0
  60. package/dist/package/src/rpc/system/admin/v1/base_role.ts +1 -1
  61. package/dist/package/src/rpc/system/admin/v1/base_session.ts +1 -1
  62. package/dist/package/src/rpc/system/admin/v1/base_table_archive.ts +1 -1
  63. package/dist/package/src/rpc/system/admin/v1/base_table_archive_record.ts +1 -1
  64. package/dist/package/src/rpc/system/admin/v1/base_table_archive_restore.ts +1 -1
  65. package/dist/package/src/rpc/system/admin/v1/base_table_backup.ts +1 -1
  66. package/dist/package/src/rpc/system/admin/v1/base_table_backup_record.ts +1 -1
  67. package/dist/package/src/rpc/system/admin/v1/base_table_backup_restore.ts +1 -1
  68. package/dist/package/src/rpc/system/admin/v1/base_table_source.ts +1 -1
  69. package/dist/package/src/rpc/system/admin/v1/base_tenant.ts +1 -1
  70. package/dist/package/src/rpc/system/admin/v1/base_third_account.ts +1 -1
  71. package/dist/package/src/rpc/system/admin/v1/base_user.ts +1 -1
  72. package/dist/package/src/rpc/system/admin/v1/cache.ts +1 -1
  73. package/dist/package/src/rpc/system/admin/v1/code_gen.ts +1 -1
  74. package/dist/package/src/rpc/system/admin/v1/code_gen_column.ts +1 -1
  75. package/dist/package/src/rpc/system/admin/v1/code_gen_proto.ts +1 -1
  76. package/dist/package/src/rpc/system/admin/v1/code_gen_table.ts +1 -1
  77. package/dist/package/src/rpc/system/admin/v1/common.ts +1 -1
  78. package/dist/package/src/rpc/system/admin/v1/oauth_client.ts +1 -1
  79. package/dist/package/src/rpc/system/admin/v1/ops_monitoring.ts +1 -1
  80. package/dist/package/src/rpc/system/admin/v1/project_document.ts +1 -1
  81. package/dist/package/src/rpc/system/admin/v1/runtime_log.ts +1 -1
  82. package/dist/package/src/rpc/system/common/v1/common.ts +1 -1
  83. package/dist/package/src/rpc/system/config/v1/system_config.ts +1 -1
  84. package/dist/package/src/views/base/redact-output-policy/index.vue +324 -0
  85. package/dist/package/src/views/base/redact-rule/index.vue +339 -29
  86. package/dist/package/src/views/base/redact-storage-policy/index.vue +276 -0
  87. package/package.json +2 -2
  88. package/dist/package/declarations/src/api/system/base_redact_field.d.ts +0 -20
  89. package/dist/package/declarations/src/api/system/base_redact_policy.d.ts +0 -19
  90. package/dist/package/declarations/src/rpc/system/admin/v1/base_redact_field.d.ts +0 -161
  91. package/dist/package/declarations/src/rpc/system/admin/v1/base_redact_policy.d.ts +0 -150
  92. package/dist/package/src/api/system/base_redact_field.ts +0 -25
  93. package/dist/package/src/api/system/base_redact_policy.ts +0 -24
  94. package/dist/package/src/rpc/system/admin/v1/base_redact_field.ts +0 -182
  95. package/dist/package/src/rpc/system/admin/v1/base_redact_policy.ts +0 -174
  96. package/dist/package/src/views/base/redact-field/index.vue +0 -59
  97. package/dist/package/src/views/base/redact-policy/index.vue +0 -92
  98. /package/dist/package/declarations/src/views/base/{redact-field → redact-output-policy}/index.vue.d.ts +0 -0
  99. /package/dist/package/declarations/src/views/base/{redact-policy → redact-storage-policy}/index.vue.d.ts +0 -0
@@ -0,0 +1,276 @@
1
+ <template>
2
+ <div class="table-box">
3
+ <ProTable ref="table" row-key="id" :columns="columns" :header-actions="headerActions" :request-api="requestTable" />
4
+ <FormDialog
5
+ v-model="dialog.visible"
6
+ ref="dialogRef"
7
+ :title="t(dialog.titleKey)"
8
+ width="1180px"
9
+ top="3vh"
10
+ label-width="150px"
11
+ destroy-on-close
12
+ :model="form"
13
+ :fields="fields"
14
+ :rules="rules"
15
+ @confirm="submit"
16
+ @close="resetForm"
17
+ >
18
+ <template #column_rows>
19
+ <div class="field-table">
20
+ <div class="field-table__summary">
21
+ {{ t("system.base.redact_storage_policy.message.configured_fields", { count: configuredFieldCount }) }}
22
+ </div>
23
+ <el-table :data="form.column_rows" row-key="value" border height="500">
24
+ <el-table-column :label="t('system.base.redact_storage_policy.field.column_name')" min-width="260">
25
+ <template #default="{ row }">
26
+ <div class="field-cell">
27
+ <div class="field-cell__title">{{ row.name }}</div>
28
+ <div class="field-cell__meta">{{ row.comment }}<span v-if="row.db_type"> · {{ row.db_type }}</span></div>
29
+ </div>
30
+ </template>
31
+ </el-table-column>
32
+ <el-table-column :label="t('system.base.redact_storage_policy.field.rule')" width="270">
33
+ <template #default="{ row }">
34
+ <el-select v-model="row.rule_id" class="table-control" size="small" clearable @change="handleRuleChange(row)">
35
+ <el-option v-for="option in ruleOptions" :key="String(option.value)" :label="option.label" :value="option.value" :disabled="option.disabled" />
36
+ </el-select>
37
+ </template>
38
+ </el-table-column>
39
+ <el-table-column :label="t('system.base.redact_storage_policy.field.parameters')" min-width="520">
40
+ <template #default="{ row }">
41
+ <div v-if="row.rule_id" class="parameter-grid">
42
+ <template v-if="row.rule_type === 'MASK'">
43
+ <ParameterNumber v-model="row.params.keep_first" :label="t('system.base.redact_rule.parameter.keep_first')" />
44
+ <ParameterNumber v-model="row.params.keep_last" :label="t('system.base.redact_rule.parameter.keep_last')" />
45
+ <ParameterText v-model="row.params.mask_char" :label="t('system.base.redact_rule.parameter.mask_char')" />
46
+ </template>
47
+ <template v-else-if="row.rule_type === 'EMAIL'">
48
+ <ParameterNumber v-model="row.params.keep_local_first" :label="t('system.base.redact_rule.parameter.keep_local_first')" />
49
+ <div class="parameter-item"><span>{{ t("system.base.redact_rule.parameter.mask_domain") }}</span><el-switch v-model="row.params.mask_domain" /></div>
50
+ <ParameterText v-model="row.params.mask_char" :label="t('system.base.redact_rule.parameter.mask_char')" />
51
+ </template>
52
+ <template v-else-if="row.rule_type === 'REGEX'">
53
+ <ParameterText v-model="row.params.pattern" :label="t('system.base.redact_rule.parameter.pattern')" />
54
+ <ParameterText v-model="row.params.replacement" :label="t('system.base.redact_rule.parameter.replacement')" />
55
+ </template>
56
+ <template v-else-if="row.rule_type === 'TRUNCATE'">
57
+ <ParameterNumber v-model="row.params.length" :label="t('system.base.redact_rule.parameter.length')" />
58
+ <ParameterText v-model="row.params.suffix" :label="t('system.base.redact_rule.parameter.suffix')" />
59
+ </template>
60
+ <template v-else-if="row.rule_type === 'HASH'">
61
+ <div class="parameter-item"><span>{{ t("system.base.redact_rule.parameter.algo") }}</span><el-select v-model="row.params.algo" class="parameter-control" size="small"><el-option label="MD5" value="MD5" /><el-option label="SHA1" value="SHA1" /><el-option label="SHA256" value="SHA256" /></el-select></div>
62
+ </template>
63
+ <template v-else-if="row.rule_type === 'IP'">
64
+ <ParameterNumber v-model="row.params.keep_octets" :label="t('system.base.redact_rule.parameter.keep_octets')" />
65
+ <ParameterText v-model="row.params.mask_char" :label="t('system.base.redact_rule.parameter.mask_char')" />
66
+ </template>
67
+ <template v-else-if="row.rule_type === 'URL'">
68
+ <div class="parameter-item"><span>{{ t("system.base.redact_rule.parameter.mask_query") }}</span><el-switch v-model="row.params.mask_query" /></div>
69
+ <ParameterText v-model="row.params.mask_char" :label="t('system.base.redact_rule.parameter.mask_char')" />
70
+ </template>
71
+ <template v-else-if="row.rule_type === 'FIXED_LENGTH'">
72
+ <ParameterText v-model="row.params.char" :label="t('system.base.redact_rule.parameter.char')" />
73
+ </template>
74
+ </div>
75
+ <span v-else class="empty-value">--</span>
76
+ </template>
77
+ </el-table-column>
78
+ </el-table>
79
+ </div>
80
+ </template>
81
+ </FormDialog>
82
+ </div>
83
+ </template>
84
+
85
+ <script setup lang="ts">
86
+ import { computed, defineComponent, h, reactive, ref } from "vue";
87
+ import type { FormRules } from "element-plus";
88
+ import type { ColumnProps, HeaderActionProps, ProTableInstance } from "@liujitcn/kratos-admin-core/components/ProTable/interface";
89
+ import ProTable from "@liujitcn/kratos-admin-core/components/ProTable";
90
+ import FormDialog from "@liujitcn/kratos-admin-core/components/Dialog/FormDialog.vue";
91
+ import type { ProFormField, ProFormOption } from "@liujitcn/kratos-admin-core/components/ProForm/interface";
92
+ import { useAuthButtons } from "@liujitcn/kratos-admin-core/auth";
93
+ import { buildPageRequest, normalizeSelectedIds } from "@liujitcn/kratos-admin-core/table";
94
+ import { t } from "@liujitcn/kratos-admin-core";
95
+ import { defBaseTableSourceService } from "@liujitcn/kratos-admin-system/api/system/admin/v1/base_table_source";
96
+ import { defCodeGenColumnService } from "@liujitcn/kratos-admin-system/api/system/admin/v1/code_gen_column";
97
+ import { defCodeGenTableService } from "@liujitcn/kratos-admin-system/api/system/admin/v1/code_gen_table";
98
+ import { defBaseRedactRuleService } from "@liujitcn/kratos-admin-system/api/system/admin/v1/base_redact_rule";
99
+ import { defBaseRedactStoragePolicyService } from "@liujitcn/kratos-admin-system/api/system/admin/v1/base_redact_storage_policy";
100
+ import type { CodeGenDatabaseTable } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/code_gen_table";
101
+ import type { BaseRedactRule } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_redact_rule";
102
+ import type { BaseRedactStoragePolicy, BaseRedactStoragePolicyForm, PageBaseRedactStoragePolicyRequest } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_redact_storage_policy";
103
+ import { Status } from "@liujitcn/kratos-admin-system/rpc/common/v1/enum";
104
+
105
+ /** 脱敏规则参数。 */
106
+ interface RuleParams {
107
+ keep_first?: number;
108
+ keep_last?: number;
109
+ mask_char?: string;
110
+ keep_local_first?: number;
111
+ mask_domain?: boolean;
112
+ pattern?: string;
113
+ replacement?: string;
114
+ length?: number;
115
+ suffix?: string;
116
+ algo?: string;
117
+ keep_octets?: number;
118
+ mask_query?: boolean;
119
+ char?: string;
120
+ }
121
+
122
+ /** 入库字段表格行。 */
123
+ interface StorageColumnRow extends ProFormOption {
124
+ /** 数据库字段名。 */
125
+ name: string;
126
+ /** 数据库字段注释。 */
127
+ comment: string;
128
+ /** 数据库字段类型。 */
129
+ db_type: string;
130
+ /** 已有策略 ID。 */
131
+ id: number;
132
+ /** 脱敏规则 ID。 */
133
+ rule_id?: number;
134
+ /** 脱敏规则类型。 */
135
+ rule_type: string;
136
+ /** 脱敏规则参数对象。 */
137
+ params: RuleParams;
138
+ /** 脱敏规则参数 JSON。 */
139
+ rule_params: string;
140
+ }
141
+
142
+ /** 入库脱敏表单状态。 */
143
+ interface StorageFormState extends BaseRedactStoragePolicyForm {
144
+ /** 当前选择的字段表格。 */
145
+ column_rows: StorageColumnRow[];
146
+ }
147
+
148
+ /** 入库表格行事件使用的最小字段视图。 */
149
+ interface StorageTableRow {
150
+ /** 脱敏规则 ID。 */
151
+ rule_id?: number;
152
+ /** 脱敏规则类型。 */
153
+ rule_type?: string;
154
+ /** 脱敏规则参数对象。 */
155
+ params?: RuleParams;
156
+ /** 脱敏规则参数 JSON。 */
157
+ rule_params?: string;
158
+ }
159
+
160
+ const STORAGE_AUDIT_COLUMN_NAMES = new Set([
161
+ "id", "created_at", "created_by", "updated_at", "updated_by", "deleted_at", "deleted_by",
162
+ "create_time", "creator", "creator_id", "update_time", "updater", "updater_id", "delete_time", "deleter", "deleter_id"
163
+ ]);
164
+ const ParameterText = defineComponent({
165
+ props: { modelValue: { type: [String, Number], default: "" }, label: { type: String, required: true } },
166
+ emits: ["update:modelValue"],
167
+ setup(props, { emit }) {
168
+ return () => h("div", { class: "parameter-item" }, [h("span", props.label), h("input", { class: "el-input__inner", value: props.modelValue, onInput: (event: Event) => emit("update:modelValue", (event.target as HTMLInputElement).value) })]);
169
+ }
170
+ });
171
+ const ParameterNumber = defineComponent({
172
+ props: { modelValue: { type: Number, default: 0 }, label: { type: String, required: true } },
173
+ emits: ["update:modelValue"],
174
+ setup(props, { emit }) {
175
+ return () => h("div", { class: "parameter-item" }, [h("span", props.label), h("input", { class: "el-input__inner", type: "number", min: 0, value: props.modelValue, onInput: (event: Event) => emit("update:modelValue", Number((event.target as HTMLInputElement).value)) })]);
176
+ }
177
+ });
178
+
179
+ defineOptions({ name: "BaseRedactStoragePolicy", inheritAttrs: false });
180
+ const { BUTTONS } = useAuthButtons();
181
+ const table = ref<ProTableInstance>();
182
+ const dialogRef = ref<InstanceType<typeof FormDialog>>();
183
+ const sourceOptions = ref<ProFormOption[]>([]);
184
+ const tableOptions = ref<ProFormOption[]>([]);
185
+ const tableCommentMap = ref(new Map<string, string>());
186
+ const ruleOptions = ref<ProFormOption[]>([]);
187
+ const ruleCatalog = ref<BaseRedactRule[]>([]);
188
+ const dialog = reactive({ visible: false, titleKey: "common.action.create_resource" });
189
+ const form = reactive<StorageFormState>(defaultForm());
190
+ const statusOptions = computed<ProFormOption[]>(() => [{ label: t("common.status.enabled"), value: Status.STATUS_ENABLE }, { label: t("common.status.disabled"), value: Status.STATUS_DISABLE }]);
191
+ const configuredFieldCount = computed(() => form.column_rows.filter(row => Boolean(row.rule_id)).length);
192
+ const fields = computed<ProFormField[]>(() => [
193
+ { prop: "source_name", label: t("system.base.redact_storage_policy.field.source_name"), component: "select", props: { filterable: true, disabled: Boolean(form.id), onChange: handleSourceChange }, options: sourceOptions.value },
194
+ { prop: "table_name", label: t("system.base.redact_storage_policy.field.table_name"), component: "select", props: { filterable: true, disabled: Boolean(form.id) || !form.source_name, onChange: handleTableChange }, options: tableOptions.value },
195
+ { prop: "column_rows", label: t("system.base.redact_storage_policy.field.column_name"), component: "slot", slotName: "column_rows", colSpan: 24, visible: () => Boolean(form.table_name) },
196
+ { prop: "status", label: t("common.field.status"), component: "radio-group", options: statusOptions.value },
197
+ { prop: "remark", label: t("common.field.remark"), component: "textarea" }
198
+ ]);
199
+ const rules = computed<FormRules>(() => ({
200
+ source_name: [{ required: true, message: t("system.base.redact_storage_policy.validation.source_name"), trigger: "change" }],
201
+ table_name: [{ required: true, message: t("system.base.redact_storage_policy.validation.table_name"), trigger: "change" }],
202
+ column_rows: [{ validator: (_rule, value: StorageColumnRow[], callback) => value?.some(row => Boolean(row.rule_id)) ? callback() : callback(new Error(t("system.base.redact_storage_policy.validation.configured_fields"))), trigger: "change" }]
203
+ }));
204
+ const columns = computed<ColumnProps[]>(() => [
205
+ { type: "selection", width: 55 },
206
+ { prop: "source_name", label: t("system.base.redact_storage_policy.field.source_name"), minWidth: 130, search: { el: "input" } },
207
+ { prop: "table_name", label: t("system.base.redact_storage_policy.field.table_name"), minWidth: 180, search: { el: "input" }, render: scope => tableLabel(scope.row as BaseRedactStoragePolicy) },
208
+ { prop: "column_name", label: t("system.base.redact_storage_policy.field.column_name"), minWidth: 150, search: { el: "input" } },
209
+ { prop: "rule_name", label: t("system.base.redact_storage_policy.field.rule"), minWidth: 150 },
210
+ { prop: "status", label: t("common.field.status"), width: 100, cellType: "status", statusProps: { activeValue: Status.STATUS_ENABLE, inactiveValue: Status.STATUS_DISABLE, activeText: t("common.status.enabled"), inactiveText: t("common.status.disabled"), disabled: () => !BUTTONS.value["base:redact-storage-policy:status"], beforeChange: scope => changeStatus(scope.row as BaseRedactStoragePolicy) } },
211
+ { prop: "actions", label: t("common.field.operation"), width: 150, fixed: "right", cellType: "actions", actions: [{ label: t("common.action.edit"), type: "primary", link: true, icon: EditPen, hidden: () => !BUTTONS.value["base:redact-storage-policy:update"], onClick: scope => openDialog((scope.row as BaseRedactStoragePolicy).id) }, { label: t("common.action.delete"), type: "danger", link: true, icon: Delete, hidden: () => !BUTTONS.value["base:redact-storage-policy:delete"], onClick: scope => deleteItems(scope.row as BaseRedactStoragePolicy) }] }
212
+ ]);
213
+ const headerActions = computed<HeaderActionProps[]>(() => [{ label: t("common.action.create"), type: "success", icon: CirclePlus, hidden: () => !BUTTONS.value["base:redact-storage-policy:create"], onClick: () => openDialog() }, { label: t("common.action.delete"), type: "danger", icon: Delete, hidden: () => !BUTTONS.value["base:redact-storage-policy:delete"], disabled: scope => !scope.selectedList.length, onClick: scope => deleteItems(scope.selectedList as BaseRedactStoragePolicy[]) }]);
214
+
215
+ /** 请求入库脱敏策略分页列表。 */
216
+ async function requestTable(params: PageBaseRedactStoragePolicyRequest) { const data = await defBaseRedactStoragePolicyService.PageBaseRedactStoragePolicy(buildPageRequest(params)); return { data: { list: data.base_redact_storage_policies ?? [], total: data.total } }; }
217
+ /** 加载脱敏规则选项。 */
218
+ async function loadRules() { const data = await defBaseRedactRuleService.PageBaseRedactRule({ code: "", name: "", rule_type: "", page_num: 1, page_size: 100 }); ruleCatalog.value = data.base_redact_rules ?? []; ruleOptions.value = ruleCatalog.value.map(item => ({ label: `${item.name} (${item.code})`, value: item.id, disabled: item.status !== Status.STATUS_ENABLE })); }
219
+ /** 数据源变更后清空下级选择并加载数据表。 */
220
+ async function handleSourceChange(sourceName: string) { form.source_name = sourceName; form.table_name = ""; form.column_name = ""; form.column_rows = []; tableOptions.value = []; await loadTables(); }
221
+ /** 数据表变更后加载字段表格。 */
222
+ async function handleTableChange(tableName: string) { form.table_name = tableName; form.column_name = ""; form.column_rows = []; await loadColumns(); }
223
+ /** 加载数据源选项。 */
224
+ async function loadSourceOptions() { const data = await defBaseTableSourceService.OptionBaseTableSource({}); sourceOptions.value = (data.value ?? []).map(value => ({ label: value, value })); }
225
+ /** 加载指定数据源的数据表选项。 */
226
+ async function loadTables(sourceName = form.source_name) { if (!sourceName) { tableOptions.value = []; return; } const data = await defCodeGenTableService.ListCodeGenDatabaseTable({ source_name: sourceName }); tableOptions.value = (data.tables ?? []).map((item: CodeGenDatabaseTable) => ({ label: item.comment ? `${item.comment}(${item.name})` : item.name, value: item.name })); }
227
+ /** 预加载数据表中文注释,供列表显示。 */
228
+ async function loadTableComments() { await loadSourceOptions(); const comments = new Map<string, string>(); await Promise.all(sourceOptions.value.map(async option => { const sourceName = String(option.value); const data = await defCodeGenTableService.ListCodeGenDatabaseTable({ source_name: sourceName }); for (const item of data.tables ?? []) { if (item.comment) comments.set(`${sourceName}\x00${item.name}`, item.comment); } })); tableCommentMap.value = comments; }
229
+ /** 加载并过滤数据库字段。 */
230
+ async function loadColumns() { if (!form.source_name || !form.table_name) { form.column_rows = []; return; } const data = await defCodeGenColumnService.ListCodeGenDatabaseColumn({ source_name: form.source_name, table_name: form.table_name }); form.column_rows = (data.columns ?? []).filter(item => !item.is_primary && !STORAGE_AUDIT_COLUMN_NAMES.has(item.name.toLowerCase())).map(item => createColumnRow({ label: item.name, value: item.name, name: item.name, comment: item.comment, db_type: item.db_type })); }
231
+ /** 打开新增或编辑弹窗。 */
232
+ async function openDialog(id?: number) { resetForm(); await Promise.all([loadSourceOptions(), loadRules()]); if (id !== undefined) { const data = await defBaseRedactStoragePolicyService.GetBaseRedactStoragePolicy({ id }); Object.assign(form, data); await loadTables(); await loadColumns(); const row = form.column_rows.find(item => item.name === data.column_name); if (row) applyPolicy(row, data); } dialog.titleKey = id !== undefined ? "common.action.edit_resource" : "common.action.create_resource"; dialog.visible = true; }
233
+ /** 重置弹窗表单。 */
234
+ function resetForm() { dialog.visible = false; dialogRef.value?.resetFields(); Object.assign(form, defaultForm()); sourceOptions.value = []; tableOptions.value = []; }
235
+ /** 保存表格中已配置的全部字段。 */
236
+ async function submit() { const valid = await dialogRef.value?.validate(); if (!valid || !form.column_rows.some(row => Boolean(row.rule_id))) return; const rows = form.column_rows.filter(row => Boolean(row.rule_id)); const createPolicies = rows.filter(row => !row.id).map(buildPayload); const updatePolicies = rows.filter(row => Boolean(row.id)).map(buildPayload); const requests: Promise<unknown>[] = []; if (createPolicies.length) requests.push(defBaseRedactStoragePolicyService.CreateBaseRedactStoragePolicy({ base_redact_storage_policy: createPolicies })); if (updatePolicies.length) requests.push(defBaseRedactStoragePolicyService.UpdateBaseRedactStoragePolicy({ base_redact_storage_policy: updatePolicies })); await Promise.all(requests); ElMessage.success(t("system.base.redact_storage_policy.message.batch_save_success", { count: rows.length })); resetForm(); table.value?.getTableList(); }
237
+ /** 将表格行转换为入库策略请求。 */
238
+ function buildPayload(row: StorageColumnRow): BaseRedactStoragePolicyForm { syncRowParams(row); return { id: row.id, source_name: form.source_name, table_name: form.table_name, column_name: row.name, rule_id: row.rule_id ?? 0, rule_params: row.rule_params, status: form.status, remark: form.remark }; }
239
+ /** 将已保存的策略回填到对应字段行。 */
240
+ function applyPolicy(row: StorageColumnRow, data: BaseRedactStoragePolicyForm) { row.id = data.id; row.rule_id = data.rule_id || undefined; row.rule_params = data.rule_params; if (row.rule_id) { const rule = ruleCatalog.value.find(item => item.id === row.rule_id); row.rule_type = rule?.rule_type ?? ""; row.params = parseParams(row.rule_type, row.rule_params); } }
241
+ /** 处理行规则变更。 */
242
+ function handleRuleChange(row: StorageTableRow) { const rule = ruleCatalog.value.find(item => item.id === row.rule_id); row.rule_type = rule?.rule_type ?? ""; row.params = rule ? parseParams(rule.rule_type, rule.rule) : {}; row.rule_params = rule ? rule.rule : "{}"; }
243
+ /** 同步单行规则参数。 */
244
+ function syncRowParams(row: StorageColumnRow) { const rule = ruleCatalog.value.find(item => item.id === row.rule_id); if (rule) { row.rule_type = rule.rule_type; row.rule_params = JSON.stringify({ [rule.rule_type.toLowerCase()]: row.params }); } }
245
+ /** 创建空的入库字段行。 */
246
+ function createColumnRow(option: Pick<StorageColumnRow, "label" | "value" | "name" | "comment" | "db_type">): StorageColumnRow { return { ...option, id: 0, rule_id: undefined, rule_type: "", params: {}, rule_params: "{}" }; }
247
+ /** 解析规则参数。 */
248
+ function parseParams(ruleType: string, raw: string): RuleParams { try { const value = JSON.parse(raw) as Record<string, RuleParams>; return value[ruleType.toLowerCase()] ?? defaultParams(ruleType); } catch { return defaultParams(ruleType); } }
249
+ /** 返回规则默认参数。 */
250
+ function defaultParams(ruleType: string): RuleParams { switch (ruleType) { case "MASK": return { keep_first: 3, keep_last: 4, mask_char: "*" }; case "EMAIL": return { keep_local_first: 2, mask_domain: false, mask_char: "*" }; case "REGEX": return { pattern: "(?s).+", replacement: "[REDACTED]" }; case "TRUNCATE": return { length: 10, suffix: "..." }; case "HASH": return { algo: "SHA256" }; case "IP": return { keep_octets: 2, mask_char: "x" }; case "URL": return { mask_query: true, mask_char: "*" }; case "FIXED_LENGTH": return { char: "X" }; default: return {}; } }
251
+ /** 修改入库策略状态。 */
252
+ async function changeStatus(row: BaseRedactStoragePolicy) { const next = row.status === Status.STATUS_ENABLE ? Status.STATUS_DISABLE : Status.STATUS_ENABLE; try { await ElMessageBox.confirm(t("common.dialog.status_change", { action: t(next === Status.STATUS_ENABLE ? "common.status.enabled" : "common.status.disabled"), resource: t("system.base.redact_storage_policy.title"), field: t("system.base.redact_storage_policy.field.column_name"), value: row.column_name }), t("common.title.warning"), { type: "warning" }); await defBaseRedactStoragePolicyService.SetBaseRedactStoragePolicyStatus({ id: row.id, status: next }); table.value?.getTableList(); return true; } catch { return false; } }
253
+ /** 删除选中的入库策略。 */
254
+ function deleteItems(selected?: BaseRedactStoragePolicy | BaseRedactStoragePolicy[] | number | string | Array<number | string>) { const items = Array.isArray(selected) ? selected.filter((item): item is BaseRedactStoragePolicy => typeof item === "object") : selected && typeof selected === "object" ? [selected] : []; const ids = items.length ? items.map(item => item.id) : normalizeSelectedIds(selected as number | string | Array<number | string>); if (!ids.length) { ElMessage.warning(t("common.message.select_delete_item")); return; } ElMessageBox.confirm(t("common.dialog.delete_selected", { resource: t("system.base.redact_storage_policy.title") }), t("common.title.warning"), { type: "warning" }).then(async () => { await defBaseRedactStoragePolicyService.DeleteBaseRedactStoragePolicy({ id: ids.join(",") }); ElMessage.success(t("common.message.delete_success", { resource: t("system.base.redact_storage_policy.title") })); table.value?.getTableList(); }); }
255
+ /** 创建默认入库表单。 */
256
+ function defaultForm(): StorageFormState { return { id: 0, source_name: "", table_name: "", column_name: "", column_rows: [], rule_id: 0, rule_params: "{}", status: Status.STATUS_ENABLE, remark: "" }; }
257
+
258
+ /** 格式化列表中的数据表名称。 */
259
+ function tableLabel(row: BaseRedactStoragePolicy) { const comment = tableCommentMap.value.get(`${row.source_name}\x00${row.table_name}`); return comment && comment !== row.table_name ? `${comment}(${row.table_name})` : row.table_name; }
260
+
261
+ void loadTableComments().catch(() => undefined);
262
+ </script>
263
+
264
+ <style scoped lang="scss">
265
+ .field-table { width: 100%; }
266
+ .field-table__summary { margin-bottom: 8px; color: var(--el-text-color-secondary); line-height: 1.5; }
267
+ .field-cell { min-width: 0; line-height: 1.35; }
268
+ .field-cell__title { overflow: hidden; color: var(--el-text-color-regular); text-overflow: ellipsis; white-space: nowrap; }
269
+ .field-cell__meta { overflow: hidden; color: var(--el-text-color-secondary); font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }
270
+ .table-control { width: 100%; }
271
+ .parameter-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; min-width: 480px; }
272
+ .parameter-item { display: flex; flex-direction: column; gap: 4px; min-width: 0; color: var(--el-text-color-regular); font-size: 12px; }
273
+ .parameter-control { width: 100%; }
274
+ .empty-value { color: var(--el-text-color-secondary); }
275
+ @media (max-width: 900px) { .parameter-grid { grid-template-columns: minmax(0, 1fr); min-width: 0; } }
276
+ </style>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@liujitcn/kratos-admin-system",
3
3
  "private": false,
4
- "version": "0.0.32",
4
+ "version": "0.0.34",
5
5
  "type": "module",
6
6
  "description": "kratos-admin system management module",
7
7
  "license": "MIT",
@@ -15,7 +15,7 @@
15
15
  "sortablejs": "^1.15.2",
16
16
  "swagger-ui-dist": "^5.32.9",
17
17
  "vue-element-plus-x": "^2.0.3",
18
- "@liujitcn/kratos-admin-core": "0.0.32"
18
+ "@liujitcn/kratos-admin-core": "0.0.34"
19
19
  },
20
20
  "peerDependencies": {
21
21
  "@element-plus/icons-vue": "^2.3.1",
@@ -1,20 +0,0 @@
1
- import type { BaseRedactFieldForm, BaseRedactFieldService, DeleteBaseRedactFieldRequest, GetBaseRedactFieldRequest, OptionBaseRedactFieldRequest, PageBaseRedactFieldRequest, PageBaseRedactFieldResponse, SetBaseRedactFieldStatusRequest, UpdateBaseRedactFieldRequest } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_redact_field";
2
- import type { SelectOptionResponse } from "@liujitcn/kratos-admin-system/rpc/common/v1/common";
3
- import type { Empty } from "@liujitcn/kratos-admin-system/rpc/google/protobuf/empty";
4
- /** Admin脱敏字段目录服务。 */
5
- export declare class BaseRedactFieldServiceImpl implements BaseRedactFieldService {
6
- /** 查询脱敏字段选项。 */
7
- OptionBaseRedactField(request?: OptionBaseRedactFieldRequest): Promise<SelectOptionResponse>;
8
- /** 查询脱敏字段分页列表。 */
9
- PageBaseRedactField(request: PageBaseRedactFieldRequest): Promise<PageBaseRedactFieldResponse>;
10
- /** 查询脱敏字段详情。 */
11
- GetBaseRedactField(request: GetBaseRedactFieldRequest): Promise<BaseRedactFieldForm>;
12
- /** 更新脱敏字段。 */
13
- UpdateBaseRedactField(request: UpdateBaseRedactFieldRequest): Promise<Empty>;
14
- /** 删除脱敏字段。 */
15
- DeleteBaseRedactField(request: DeleteBaseRedactFieldRequest): Promise<Empty>;
16
- /** 设置脱敏字段状态。 */
17
- SetBaseRedactFieldStatus(request: SetBaseRedactFieldStatusRequest): Promise<Empty>;
18
- }
19
- /** defBaseRedactFieldService 脱敏字段目录服务实例。 */
20
- export declare const defBaseRedactFieldService: BaseRedactFieldServiceImpl;
@@ -1,19 +0,0 @@
1
- import type { BaseRedactPolicyForm, BaseRedactPolicyService, CreateBaseRedactPolicyRequest, DeleteBaseRedactPolicyRequest, GetBaseRedactPolicyRequest, PageBaseRedactPolicyRequest, PageBaseRedactPolicyResponse, SetBaseRedactPolicyStatusRequest, UpdateBaseRedactPolicyRequest } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_redact_policy";
2
- import type { Empty } from "@liujitcn/kratos-admin-system/rpc/google/protobuf/empty";
3
- /** Admin脱敏策略绑定服务。 */
4
- export declare class BaseRedactPolicyServiceImpl implements BaseRedactPolicyService {
5
- /** 查询脱敏策略分页列表。 */
6
- PageBaseRedactPolicy(request: PageBaseRedactPolicyRequest): Promise<PageBaseRedactPolicyResponse>;
7
- /** 查询脱敏策略详情。 */
8
- GetBaseRedactPolicy(request: GetBaseRedactPolicyRequest): Promise<BaseRedactPolicyForm>;
9
- /** 创建脱敏策略。 */
10
- CreateBaseRedactPolicy(request: CreateBaseRedactPolicyRequest): Promise<Empty>;
11
- /** 更新脱敏策略。 */
12
- UpdateBaseRedactPolicy(request: UpdateBaseRedactPolicyRequest): Promise<Empty>;
13
- /** 删除脱敏策略。 */
14
- DeleteBaseRedactPolicy(request: DeleteBaseRedactPolicyRequest): Promise<Empty>;
15
- /** 设置脱敏策略状态。 */
16
- SetBaseRedactPolicyStatus(request: SetBaseRedactPolicyStatusRequest): Promise<Empty>;
17
- }
18
- /** defBaseRedactPolicyService 脱敏策略绑定服务实例。 */
19
- export declare const defBaseRedactPolicyService: BaseRedactPolicyServiceImpl;
@@ -1,161 +0,0 @@
1
- import type { SelectOptionResponse } from "../../../common/v1/common";
2
- import type { Status } from "../../../common/v1/enum";
3
- import type { Empty } from "../../../google/protobuf/empty";
4
- import type { BaseRedactDirection } from "./base_redact_common";
5
- /** 字段数据库存储方式。 */
6
- export declare enum BaseRedactStorageMode {
7
- /** BASE_REDACT_STORAGE_MODE_UNSPECIFIED - 未配置存储方式,服务端拒绝启用字段存储保护。 */
8
- BASE_REDACT_STORAGE_MODE_UNSPECIFIED = 0,
9
- /** BASE_REDACT_STORAGE_MODE_PLAIN - 主表保存明文。 */
10
- BASE_REDACT_STORAGE_MODE_PLAIN = 1,
11
- /** BASE_REDACT_STORAGE_MODE_MASK - 主表保存脱敏值,旁表保存加密原文。 */
12
- BASE_REDACT_STORAGE_MODE_MASK = 2,
13
- /** BASE_REDACT_STORAGE_MODE_HASH - 主表保存不可逆哈希。 */
14
- BASE_REDACT_STORAGE_MODE_HASH = 3
15
- }
16
- /** 敏感字段查询方式。 */
17
- export declare enum BaseRedactSearchMode {
18
- /** BASE_REDACT_SEARCH_MODE_UNSPECIFIED - 未配置查询方式。 */
19
- BASE_REDACT_SEARCH_MODE_UNSPECIFIED = 0,
20
- /** BASE_REDACT_SEARCH_MODE_NONE - 不支持敏感字段查询。 */
21
- BASE_REDACT_SEARCH_MODE_NONE = 1,
22
- /** BASE_REDACT_SEARCH_MODE_DIGEST - 使用 HMAC 摘要进行精确查询。 */
23
- BASE_REDACT_SEARCH_MODE_DIGEST = 2
24
- }
25
- /** 脱敏字段选项查询条件。 */
26
- export interface OptionBaseRedactFieldRequest {
27
- /** 字段关键字 */
28
- keyword: string;
29
- /** 接口操作 */
30
- operation: string;
31
- /** 脱敏方向 */
32
- direction?: BaseRedactDirection | undefined;
33
- }
34
- /** 脱敏字段分页查询条件。 */
35
- export interface PageBaseRedactFieldRequest {
36
- /** Proto消息完整名称 */
37
- message_ref: string;
38
- /** 字段路径 */
39
- field_path: string;
40
- /** 敏感字段类型 */
41
- sensitivity_type: string;
42
- /** 字段来源 */
43
- source: string;
44
- /** 状态 */
45
- status?: Status | undefined;
46
- /** 当前页码 */
47
- page_num: number;
48
- /** 每页数量 */
49
- page_size: number;
50
- }
51
- /** 脱敏字段分页响应。 */
52
- export interface PageBaseRedactFieldResponse {
53
- /** 字段列表 */
54
- base_redact_fields: BaseRedactField[];
55
- /** 总数 */
56
- total: number;
57
- }
58
- /** 脱敏字段详情查询条件。 */
59
- export interface GetBaseRedactFieldRequest {
60
- id: number;
61
- }
62
- /** 脱敏字段表单。 */
63
- export interface BaseRedactFieldForm {
64
- /** 字段目录ID */
65
- id: number;
66
- /** Proto消息完整名称 */
67
- message_ref: string;
68
- /** 字段路径 */
69
- field_path: string;
70
- /** Proto字段类型 */
71
- field_kind: string;
72
- /** 敏感字段类型 */
73
- sensitivity_type: string;
74
- /** 字段来源 */
75
- source: string;
76
- /** 数据实体标识 */
77
- entity_ref: string;
78
- /** 数据库表名 */
79
- table_name: string;
80
- /** 数据库字段名 */
81
- column_name: string;
82
- /** 业务主键字段 */
83
- record_key_field: string;
84
- /** 数据库存储方式 */
85
- storage_mode: BaseRedactStorageMode;
86
- /** 存储脱敏规则ID */
87
- storage_rule_id: number;
88
- /** 敏感字段查询方式 */
89
- search_mode: BaseRedactSearchMode;
90
- /** 状态 */
91
- status: Status;
92
- /** 备注 */
93
- remark: string;
94
- }
95
- /** 更新脱敏字段请求参数。 */
96
- export interface UpdateBaseRedactFieldRequest {
97
- base_redact_field: BaseRedactFieldForm | undefined;
98
- }
99
- /** 删除脱敏字段请求参数。 */
100
- export interface DeleteBaseRedactFieldRequest {
101
- id: string;
102
- }
103
- /** 设置脱敏字段状态请求参数。 */
104
- export interface SetBaseRedactFieldStatusRequest {
105
- /** 字段目录ID */
106
- id: number;
107
- /** 状态 */
108
- status: Status;
109
- }
110
- /** 脱敏字段目录。 */
111
- export interface BaseRedactField {
112
- /** 字段目录ID */
113
- id: number;
114
- /** Proto消息完整名称 */
115
- message_ref: string;
116
- /** 字段路径 */
117
- field_path: string;
118
- /** Proto字段类型 */
119
- field_kind: string;
120
- /** 敏感字段类型 */
121
- sensitivity_type: string;
122
- /** 字段来源 */
123
- source: string;
124
- /** 数据实体标识 */
125
- entity_ref: string;
126
- /** 数据库表名 */
127
- table_name: string;
128
- /** 数据库字段名 */
129
- column_name: string;
130
- /** 业务主键字段 */
131
- record_key_field: string;
132
- /** 数据库存储方式 */
133
- storage_mode: BaseRedactStorageMode;
134
- /** 存储脱敏规则ID */
135
- storage_rule_id: number;
136
- /** 敏感字段查询方式 */
137
- search_mode: BaseRedactSearchMode;
138
- /** 状态 */
139
- status: Status;
140
- /** 备注 */
141
- remark: string;
142
- /** 创建时间 */
143
- created_at: string;
144
- /** 更新时间 */
145
- updated_at: string;
146
- }
147
- /** Admin脱敏字段目录服务。 */
148
- export interface BaseRedactFieldService {
149
- /** 查询脱敏字段选项。 */
150
- OptionBaseRedactField(request: OptionBaseRedactFieldRequest): Promise<SelectOptionResponse>;
151
- /** 查询脱敏字段分页列表。 */
152
- PageBaseRedactField(request: PageBaseRedactFieldRequest): Promise<PageBaseRedactFieldResponse>;
153
- /** 查询脱敏字段详情。 */
154
- GetBaseRedactField(request: GetBaseRedactFieldRequest): Promise<BaseRedactFieldForm>;
155
- /** 更新脱敏字段。 */
156
- UpdateBaseRedactField(request: UpdateBaseRedactFieldRequest): Promise<Empty>;
157
- /** 删除脱敏字段。 */
158
- DeleteBaseRedactField(request: DeleteBaseRedactFieldRequest): Promise<Empty>;
159
- /** 设置脱敏字段状态。 */
160
- SetBaseRedactFieldStatus(request: SetBaseRedactFieldStatusRequest): Promise<Empty>;
161
- }