|
|
@@ -0,0 +1,274 @@
|
|
|
+<template>
|
|
|
+ <div class="dynamic-data-editor">
|
|
|
+ <a-form layout="vertical" size="small">
|
|
|
+ <a-form-item label="数据源类型">
|
|
|
+ <a-select
|
|
|
+ :value="currentType"
|
|
|
+ style="width: 100%"
|
|
|
+ :options="typeOptions"
|
|
|
+ placeholder="选择类型"
|
|
|
+ @change="onTypeChange"
|
|
|
+ />
|
|
|
+ </a-form-item>
|
|
|
+
|
|
|
+ <template v-if="currentType === 'commonContent'">
|
|
|
+ <a-form-item label="模型 ID (modelId)">
|
|
|
+ <a-input-number
|
|
|
+ :value="(modelValue as IHomeCommonCategoryDynamicDataCommonContent)?.params?.modelId"
|
|
|
+ style="width: 100%"
|
|
|
+ :min="1"
|
|
|
+ placeholder="模型ID"
|
|
|
+ @update:value="(v: number | undefined) => setCommonContent('modelId', v)"
|
|
|
+ />
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item label="栏目 ID (mainBodyColumnId)">
|
|
|
+ <a-input
|
|
|
+ :value="mainBodyColumnIdDisplay('commonContent')"
|
|
|
+ placeholder="数字或逗号分隔的多个ID,如 320 或 315,316"
|
|
|
+ @change="(e: Event) => setMainBodyColumnId('commonContent', (e.target as HTMLInputElement)?.value)"
|
|
|
+ />
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item label="分类类型 ID (typeId)">
|
|
|
+ <a-input-number
|
|
|
+ :value="(modelValue as IHomeCommonCategoryDynamicDataCommonContent)?.params?.typeId"
|
|
|
+ style="width: 100%"
|
|
|
+ placeholder="可选"
|
|
|
+ @update:value="(v: number | undefined) => setCommonContent('typeId', v)"
|
|
|
+ />
|
|
|
+ </a-form-item>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template v-else-if="currentType === 'serializedApi'">
|
|
|
+ <a-form-item label="序列化接口名称 (name)">
|
|
|
+ <a-select
|
|
|
+ :value="(modelValue as IHomeCommonCategoryDynamicDataSerializedApi)?.name"
|
|
|
+ style="width: 100%"
|
|
|
+ show-search
|
|
|
+ :filter-option="filterOption"
|
|
|
+ :options="serializedApiOptions"
|
|
|
+ placeholder="选择或输入接口名"
|
|
|
+ @change="(v: string) => setSerializedApi('name', v)"
|
|
|
+ />
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item label="栏目 ID (params.mainBodyColumnId)">
|
|
|
+ <a-input
|
|
|
+ :value="mainBodyColumnIdDisplay('serializedApi')"
|
|
|
+ placeholder="可选,数字或逗号分隔"
|
|
|
+ @change="(e: Event) => setSerializedApiMainBodyColumnId((e.target as HTMLInputElement)?.value)"
|
|
|
+ />
|
|
|
+ </a-form-item>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template v-else-if="currentType === 'request'">
|
|
|
+ <a-form-item label="请求方法 (method)">
|
|
|
+ <a-select
|
|
|
+ :value="(modelValue as IHomeCommonCategoryDynamicDataRequest)?.method"
|
|
|
+ style="width: 100%"
|
|
|
+ :options="methodOptions"
|
|
|
+ @change="(v: 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE') => setRequest('method', v)"
|
|
|
+ />
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item label="请求 URL (url)">
|
|
|
+ <a-input
|
|
|
+ :value="(modelValue as IHomeCommonCategoryDynamicDataRequest)?.url"
|
|
|
+ placeholder="https://..."
|
|
|
+ @change="(e: Event) => setRequest('url', (e.target as HTMLInputElement)?.value)"
|
|
|
+ />
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item label="查询参数 (querys) JSON">
|
|
|
+ <a-input
|
|
|
+ :value="requestQuerysJson"
|
|
|
+ placeholder='{"key": "value"}'
|
|
|
+ :rows="2"
|
|
|
+ @change="(e: Event) => setRequestQuerys((e.target as HTMLInputElement)?.value)"
|
|
|
+ />
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item label="请求体参数 (params) JSON">
|
|
|
+ <a-input
|
|
|
+ :value="requestParamsJson"
|
|
|
+ placeholder='{"key": "value"}'
|
|
|
+ :rows="2"
|
|
|
+ @change="(e: Event) => setRequestParams((e.target as HTMLInputElement)?.value)"
|
|
|
+ />
|
|
|
+ </a-form-item>
|
|
|
+ </template>
|
|
|
+ </a-form>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+import { computed, ref, watch } from 'vue';
|
|
|
+import type {
|
|
|
+ IHomeCommonCategoryDynamicData,
|
|
|
+ IHomeCommonCategoryDynamicDataCommonContent,
|
|
|
+ IHomeCommonCategoryDynamicDataSerializedApi,
|
|
|
+ IHomeCommonCategoryDynamicDataRequest,
|
|
|
+} from '@/pages/article/data/CommonCategoryDynamicData';
|
|
|
+import { SerializedApiMap } from '@/pages/article/data/CommonCategoryDynamicData';
|
|
|
+
|
|
|
+const props = defineProps<{
|
|
|
+ modelValue?: IHomeCommonCategoryDynamicData | null;
|
|
|
+}>();
|
|
|
+
|
|
|
+const emit = defineEmits<{
|
|
|
+ (e: 'update:modelValue', v: IHomeCommonCategoryDynamicData | undefined): void;
|
|
|
+}>();
|
|
|
+
|
|
|
+const typeOptions = [
|
|
|
+ { value: 'commonContent', label: '通用内容 (commonContent)' },
|
|
|
+ { value: 'serializedApi', label: '序列化接口 (serializedApi)' },
|
|
|
+ { value: 'request', label: '请求 (request)' },
|
|
|
+];
|
|
|
+
|
|
|
+const methodOptions = [
|
|
|
+ { value: 'GET', label: 'GET' },
|
|
|
+ { value: 'POST', label: 'POST' },
|
|
|
+ { value: 'PUT', label: 'PUT' },
|
|
|
+ { value: 'DELETE', label: 'DELETE' },
|
|
|
+ { value: 'HEAD', label: 'HEAD' },
|
|
|
+ { value: 'OPTIONS', label: 'OPTIONS' },
|
|
|
+];
|
|
|
+
|
|
|
+const serializedApiOptions = computed(() =>
|
|
|
+ Object.keys(SerializedApiMap).map((name) => ({ value: name, label: name }))
|
|
|
+);
|
|
|
+
|
|
|
+const currentType = computed(() => props.modelValue?.type ?? null);
|
|
|
+
|
|
|
+function filterOption(input: string, option: { value: string; label: string }) {
|
|
|
+ return option.label.toLowerCase().includes(input.toLowerCase());
|
|
|
+}
|
|
|
+
|
|
|
+function mainBodyColumnIdDisplay(source: 'commonContent' | 'serializedApi'): string {
|
|
|
+ const val = source === 'commonContent'
|
|
|
+ ? (props.modelValue as IHomeCommonCategoryDynamicDataCommonContent)?.params?.mainBodyColumnId
|
|
|
+ : (props.modelValue as IHomeCommonCategoryDynamicDataSerializedApi)?.params?.mainBodyColumnId;
|
|
|
+ if (val == null) return '';
|
|
|
+ if (Array.isArray(val)) return val.join(',');
|
|
|
+ return String(val);
|
|
|
+}
|
|
|
+
|
|
|
+function parseMainBodyColumnId(input: string): string | number | number[] | undefined {
|
|
|
+ const s = input?.trim();
|
|
|
+ if (!s) return undefined;
|
|
|
+ const parts = s.split(',').map((p) => p.trim()).filter(Boolean);
|
|
|
+ if (parts.length === 0) return undefined;
|
|
|
+ if (parts.length === 1) {
|
|
|
+ const n = Number(parts[0]);
|
|
|
+ return Number.isNaN(n) ? parts[0] : n;
|
|
|
+ }
|
|
|
+ const nums = parts.map((p) => Number(p));
|
|
|
+ return nums.every((n) => !Number.isNaN(n)) ? nums : undefined;
|
|
|
+}
|
|
|
+
|
|
|
+function onTypeChange(type: 'commonContent' | 'serializedApi' | 'request') {
|
|
|
+ if (type === 'commonContent') {
|
|
|
+ emit('update:modelValue', {
|
|
|
+ type: 'commonContent',
|
|
|
+ params: { modelId: 1, mainBodyColumnId: undefined, typeId: undefined },
|
|
|
+ });
|
|
|
+ } else if (type === 'serializedApi') {
|
|
|
+ emit('update:modelValue', {
|
|
|
+ type: 'serializedApi',
|
|
|
+ name: Object.keys(SerializedApiMap)[0] ?? 'ProjectsContent',
|
|
|
+ });
|
|
|
+ } else if (type === 'request') {
|
|
|
+ emit('update:modelValue', {
|
|
|
+ type: 'request',
|
|
|
+ method: 'GET',
|
|
|
+ url: '',
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function setCommonContent(key: 'modelId' | 'typeId', value: number | undefined) {
|
|
|
+ const cur = props.modelValue as IHomeCommonCategoryDynamicDataCommonContent | undefined;
|
|
|
+ if (!cur || cur.type !== 'commonContent') return;
|
|
|
+ const next = { ...cur, params: { ...cur.params, [key]: value } };
|
|
|
+ emit('update:modelValue', next);
|
|
|
+}
|
|
|
+
|
|
|
+function setMainBodyColumnId(source: 'commonContent' | 'serializedApi', input: string) {
|
|
|
+ const parsed = parseMainBodyColumnId(input);
|
|
|
+ if (source === 'commonContent') {
|
|
|
+ const cur = props.modelValue as IHomeCommonCategoryDynamicDataCommonContent | undefined;
|
|
|
+ if (!cur || cur.type !== 'commonContent') return;
|
|
|
+ emit('update:modelValue', { ...cur, params: { ...cur.params, mainBodyColumnId: parsed } });
|
|
|
+ } else {
|
|
|
+ const cur = props.modelValue as IHomeCommonCategoryDynamicDataSerializedApi | undefined;
|
|
|
+ if (!cur || cur.type !== 'serializedApi') return;
|
|
|
+ emit('update:modelValue', { ...cur, params: { ...cur.params, mainBodyColumnId: parsed } });
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function setSerializedApi(key: 'name', value: string) {
|
|
|
+ const cur = props.modelValue as IHomeCommonCategoryDynamicDataSerializedApi | undefined;
|
|
|
+ if (!cur || cur.type !== 'serializedApi') return;
|
|
|
+ emit('update:modelValue', { ...cur, [key]: value });
|
|
|
+}
|
|
|
+
|
|
|
+function setSerializedApiMainBodyColumnId(input: string) {
|
|
|
+ const parsed = parseMainBodyColumnId(input);
|
|
|
+ const cur = props.modelValue as IHomeCommonCategoryDynamicDataSerializedApi | undefined;
|
|
|
+ if (!cur || cur.type !== 'serializedApi') return;
|
|
|
+ const params = { ...cur.params, mainBodyColumnId: parsed };
|
|
|
+ emit('update:modelValue', { ...cur, params: Object.keys(params).length ? params : undefined });
|
|
|
+}
|
|
|
+
|
|
|
+function setRequest(key: 'method' | 'url', value: string) {
|
|
|
+ const cur = props.modelValue as IHomeCommonCategoryDynamicDataRequest | undefined;
|
|
|
+ if (!cur || cur.type !== 'request') return;
|
|
|
+ emit('update:modelValue', { ...cur, [key]: value });
|
|
|
+}
|
|
|
+
|
|
|
+const requestQuerysJson = computed(() => {
|
|
|
+ const cur = props.modelValue as IHomeCommonCategoryDynamicDataRequest | undefined;
|
|
|
+ if (!cur?.querys) return '';
|
|
|
+ try {
|
|
|
+ return typeof cur.querys === 'string' ? cur.querys : JSON.stringify(cur.querys, null, 2);
|
|
|
+ } catch {
|
|
|
+ return '';
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+const requestParamsJson = computed(() => {
|
|
|
+ const cur = props.modelValue as IHomeCommonCategoryDynamicDataRequest | undefined;
|
|
|
+ if (!cur?.params) return '';
|
|
|
+ try {
|
|
|
+ return typeof cur.params === 'string' ? cur.params : JSON.stringify(cur.params, null, 2);
|
|
|
+ } catch {
|
|
|
+ return '';
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+function setRequestQuerys(str: string) {
|
|
|
+ const cur = props.modelValue as IHomeCommonCategoryDynamicDataRequest | undefined;
|
|
|
+ if (!cur || cur.type !== 'request') return;
|
|
|
+ let querys: Record<string, any> | undefined;
|
|
|
+ try {
|
|
|
+ querys = str?.trim() ? JSON.parse(str) : undefined;
|
|
|
+ } catch {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ emit('update:modelValue', { ...cur, querys });
|
|
|
+}
|
|
|
+
|
|
|
+function setRequestParams(str: string) {
|
|
|
+ const cur = props.modelValue as IHomeCommonCategoryDynamicDataRequest | undefined;
|
|
|
+ if (!cur || cur.type !== 'request') return;
|
|
|
+ let params: Record<string, any> | undefined;
|
|
|
+ try {
|
|
|
+ params = str?.trim() ? JSON.parse(str) : undefined;
|
|
|
+ } catch {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ emit('update:modelValue', { ...cur, params });
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.dynamic-data-editor {
|
|
|
+ font-size: 12px;
|
|
|
+ margin-left: 14px;
|
|
|
+}
|
|
|
+</style>
|