mirror of
				https://github.com/YunaiV/ruoyi-vue-pro.git
				synced 2025-10-31 10:37:41 +08:00 
			
		
		
		
	perf: 重构代码生成 优化性能
This commit is contained in:
		| @ -8,9 +8,6 @@ | ||||
|         <el-tab-pane label="字段信息" name="cloum"> | ||||
|           <CloumInfoForm ref="cloumInfoRef" :info="cloumCurrentRow" /> | ||||
|         </el-tab-pane> | ||||
|         <el-tab-pane label="生成信息" name="genInfo"> | ||||
|           <GenInfoForm ref="genInfoRef" :genInfo="tableCurrentRow" /> | ||||
|         </el-tab-pane> | ||||
|       </el-tabs> | ||||
|       <template #right> | ||||
|         <XButton | ||||
| @ -30,7 +27,7 @@ import { ElTabs, ElTabPane } from 'element-plus' | ||||
| import { useI18n } from '@/hooks/web/useI18n' | ||||
| import { useMessage } from '@/hooks/web/useMessage' | ||||
| import { ContentDetailWrap } from '@/components/ContentDetailWrap' | ||||
| import { BasicInfoForm, CloumInfoForm, GenInfoForm } from './components' | ||||
| import { BasicInfoForm, CloumInfoForm } from './components' | ||||
| import { getCodegenTableApi, updateCodegenTableApi } from '@/api/infra/codegen' | ||||
| import { CodegenTableVO, CodegenColumnVO, CodegenUpdateReqVO } from '@/api/infra/codegen/types' | ||||
|  | ||||
| @ -40,12 +37,11 @@ const { push } = useRouter() | ||||
| const { query } = useRoute() | ||||
| const loading = ref(false) | ||||
| const title = ref('代码生成') | ||||
| const activeName = ref('cloum') | ||||
| const activeName = ref('basicInfo') | ||||
| const cloumInfoRef = ref(null) | ||||
| const tableCurrentRow = ref<CodegenTableVO>() | ||||
| const cloumCurrentRow = ref<CodegenColumnVO[]>([]) | ||||
| const basicInfoRef = ref<ComponentRef<typeof BasicInfoForm>>() | ||||
| const genInfoRef = ref<ComponentRef<typeof GenInfoForm>>() | ||||
|  | ||||
| const getList = async () => { | ||||
|   const id = query.id as unknown as number | ||||
| @ -59,14 +55,11 @@ const getList = async () => { | ||||
| } | ||||
| const submitForm = async () => { | ||||
|   const basicInfo = unref(basicInfoRef) | ||||
|   const genInfo = unref(genInfoRef) | ||||
|   const basicForm = await basicInfo?.elFormRef?.validate()?.catch(() => {}) | ||||
|   const genForm = await genInfo?.elFormRef?.validate()?.catch(() => {}) | ||||
|   if (basicForm && genForm) { | ||||
|   if (basicForm) { | ||||
|     const basicInfoData = (await basicInfo?.getFormData()) as CodegenTableVO | ||||
|     const genInfoData = (await genInfo?.getFormData()) as CodegenTableVO | ||||
|     const genTable: CodegenUpdateReqVO = { | ||||
|       table: Object.assign({}, basicInfoData, genInfoData), | ||||
|       table: basicInfoData, | ||||
|       columns: cloumCurrentRow.value | ||||
|     } | ||||
|     await updateCodegenTableApi(genTable) | ||||
|  | ||||
| @ -2,23 +2,42 @@ | ||||
|   <Form :rules="rules" @register="register" /> | ||||
| </template> | ||||
| <script setup lang="ts"> | ||||
| import { PropType, reactive, watch } from 'vue' | ||||
| import { onMounted, PropType, reactive, ref, watch } from 'vue' | ||||
| import { required } from '@/utils/formRules' | ||||
| import { useForm } from '@/hooks/web/useForm' | ||||
| import { Form } from '@/components/Form' | ||||
| import { FormSchema } from '@/types/form' | ||||
| import { CodegenTableVO } from '@/api/infra/codegen/types' | ||||
| import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' | ||||
| import { listSimpleMenusApi } from '@/api/system/menu' | ||||
| import { handleTree, defaultProps } from '@/utils/tree' | ||||
|  | ||||
| const props = defineProps({ | ||||
|   basicInfo: { | ||||
|     type: Object as PropType<Nullable<CodegenTableVO>>, | ||||
|     default: () => null | ||||
|   } | ||||
| }) | ||||
|  | ||||
| const templateTypeOptions = getIntDictOptions(DICT_TYPE.INFRA_CODEGEN_TEMPLATE_TYPE) | ||||
| const sceneOptions = getIntDictOptions(DICT_TYPE.INFRA_CODEGEN_SCENE) | ||||
| const menuOptions = ref<any>([]) // 树形结构 | ||||
| const getTree = async () => { | ||||
|   const res = await listSimpleMenusApi() | ||||
|   menuOptions.value = handleTree(res) | ||||
| } | ||||
|  | ||||
| const rules = reactive({ | ||||
|   tableName: [required], | ||||
|   tableComment: [required], | ||||
|   className: [required], | ||||
|   author: [required] | ||||
|   author: [required], | ||||
|   templateType: [required], | ||||
|   scene: [required], | ||||
|   moduleName: [required], | ||||
|   businessName: [required], | ||||
|   businessPackage: [required], | ||||
|   classComment: [required] | ||||
| }) | ||||
| const schema = reactive<FormSchema[]>([ | ||||
|   { | ||||
| @ -45,6 +64,79 @@ const schema = reactive<FormSchema[]>([ | ||||
|       span: 12 | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     label: '生成模板', | ||||
|     field: 'templateType', | ||||
|     component: 'Select', | ||||
|     componentProps: { | ||||
|       options: templateTypeOptions | ||||
|     }, | ||||
|     colProps: { | ||||
|       span: 12 | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     label: '生成场景', | ||||
|     field: 'scene', | ||||
|     component: 'Select', | ||||
|     componentProps: { | ||||
|       options: sceneOptions | ||||
|     }, | ||||
|     colProps: { | ||||
|       span: 12 | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     label: '模块名', | ||||
|     field: 'moduleName', | ||||
|     component: 'Input', | ||||
|     labelMessage: '模块名,即一级目录,例如 system、infra、tool 等等', | ||||
|     colProps: { | ||||
|       span: 12 | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     label: '业务名', | ||||
|     field: 'businessName', | ||||
|     component: 'Input', | ||||
|     labelMessage: '业务名,即二级目录,例如 user、permission、dict 等等', | ||||
|     colProps: { | ||||
|       span: 12 | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     label: '类名称', | ||||
|     field: 'className', | ||||
|     component: 'Input', | ||||
|     labelMessage: '类名称(首字母大写),例如SysUser、SysMenu、SysDictData 等等', | ||||
|     colProps: { | ||||
|       span: 12 | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     label: '类描述', | ||||
|     field: 'classComment', | ||||
|     component: 'Input', | ||||
|     labelMessage: '用作类描述,例如 用户', | ||||
|     colProps: { | ||||
|       span: 12 | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     label: '上级菜单', | ||||
|     field: 'parentMenuId', | ||||
|     component: 'TreeSelect', | ||||
|     componentProps: { | ||||
|       data: menuOptions, | ||||
|       props: defaultProps, | ||||
|       checkStrictly: true, | ||||
|       nodeKey: 'id' | ||||
|     }, | ||||
|     labelMessage: '分配到指定菜单下,例如 系统管理', | ||||
|     colProps: { | ||||
|       span: 12 | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     label: '作者', | ||||
|     field: 'author', | ||||
| @ -81,6 +173,10 @@ watch( | ||||
|     immediate: true | ||||
|   } | ||||
| ) | ||||
| // ========== 初始化 ========== | ||||
| onMounted(async () => { | ||||
|   await getTree() | ||||
| }) | ||||
|  | ||||
| defineExpose({ | ||||
|   elFormRef, | ||||
|  | ||||
| @ -1,113 +1,117 @@ | ||||
| <template> | ||||
|   <vxe-table | ||||
|     ref="dragTable" | ||||
|     border | ||||
|     :data="info" | ||||
|     max-height="600" | ||||
|     stripe | ||||
|     class="xtable-scrollbar" | ||||
|     :column-config="{ resizable: true }" | ||||
|   > | ||||
|     <vxe-column title="字段列名" field="columnName" fixed="left" width="80" /> | ||||
|     <vxe-column title="字段描述" field="columnComment"> | ||||
|       <template #default="{ row }"> | ||||
|         <el-input v-model="row.columnComment" /> | ||||
|       </template> | ||||
|     </vxe-column> | ||||
|     <vxe-column title="物理类型" field="dataType" width="10%" /> | ||||
|     <vxe-column title="Java类型" width="10%" field="javaType"> | ||||
|       <template #default="{ row }"> | ||||
|         <el-select v-model="row.javaType"> | ||||
|           <el-option label="Long" value="Long" /> | ||||
|           <el-option label="String" value="String" /> | ||||
|           <el-option label="Integer" value="Integer" /> | ||||
|           <el-option label="Double" value="Double" /> | ||||
|           <el-option label="BigDecimal" value="BigDecimal" /> | ||||
|           <el-option label="LocalDateTime" value="LocalDateTime" /> | ||||
|           <el-option label="Boolean" value="Boolean" /> | ||||
|         </el-select> | ||||
|       </template> | ||||
|     </vxe-column> | ||||
|     <vxe-column title="java属性" width="10%" field="javaField"> | ||||
|       <template #default="{ row }"> | ||||
|         <el-input v-model="row.javaField" /> | ||||
|       </template> | ||||
|     </vxe-column> | ||||
|     <vxe-column title="插入" width="4%" field="createOperation"> | ||||
|       <template #default="{ row }"> | ||||
|         <vxe-checkbox true-label="true" false-label="false" v-model="row.createOperation" /> | ||||
|       </template> | ||||
|     </vxe-column> | ||||
|     <vxe-column title="编辑" width="4%" field="updateOperation"> | ||||
|       <template #default="{ row }"> | ||||
|         <vxe-checkbox true-label="true" false-label="false" v-model="row.updateOperation" /> | ||||
|       </template> | ||||
|     </vxe-column> | ||||
|     <vxe-column title="列表" width="4%" field="listOperationResult"> | ||||
|       <template #default="{ row }"> | ||||
|         <vxe-checkbox true-label="true" false-label="false" v-model="row.listOperationResult" /> | ||||
|       </template> | ||||
|     </vxe-column> | ||||
|     <vxe-column title="查询" width="4%" field="listOperation"> | ||||
|       <template #default="{ row }"> | ||||
|         <vxe-checkbox true-label="true" false-label="false" v-model="row.listOperation" /> | ||||
|       </template> | ||||
|     </vxe-column> | ||||
|     <vxe-column title="查询方式" width="8%" field="listOperationCondition"> | ||||
|       <template #default="{ row }"> | ||||
|         <el-select v-model="row.listOperationCondition"> | ||||
|           <el-option label="=" value="=" /> | ||||
|           <el-option label="!=" value="!=" /> | ||||
|           <el-option label=">" value=">" /> | ||||
|           <el-option label=">=" value=">=" /> | ||||
|           <el-option label="<" value="<>" /> | ||||
|           <el-option label="<=" value="<=" /> | ||||
|           <el-option label="LIKE" value="LIKE" /> | ||||
|           <el-option label="BETWEEN" value="BETWEEN" /> | ||||
|         </el-select> | ||||
|       </template> | ||||
|     </vxe-column> | ||||
|     <vxe-column title="允许空" width="4%" field="nullable"> | ||||
|       <template #default="{ row }"> | ||||
|         <vxe-checkbox true-label="true" false-label="false" v-model="row.nullable" /> | ||||
|       </template> | ||||
|     </vxe-column> | ||||
|     <vxe-column title="字段列名" field="columnName" fixed="left" width="10%" /> | ||||
|     <vxe-colgroup title="基础属性"> | ||||
|       <vxe-column title="字段描述" field="columnComment" width="10%"> | ||||
|         <template #default="{ row }"> | ||||
|           <vxe-input v-model="row.columnComment" placeholder="请输入字段描述" /> | ||||
|         </template> | ||||
|       </vxe-column> | ||||
|       <vxe-column title="物理类型" field="dataType" width="10%" /> | ||||
|       <vxe-column title="Java类型" width="10%" field="javaType"> | ||||
|         <template #default="{ row }"> | ||||
|           <vxe-select v-model="row.javaType" placeholder="请选择Java类型"> | ||||
|             <vxe-option label="Long" value="Long" /> | ||||
|             <vxe-option label="String" value="String" /> | ||||
|             <vxe-option label="Integer" value="Integer" /> | ||||
|             <vxe-option label="Double" value="Double" /> | ||||
|             <vxe-option label="BigDecimal" value="BigDecimal" /> | ||||
|             <vxe-option label="LocalDateTime" value="LocalDateTime" /> | ||||
|             <vxe-option label="Boolean" value="Boolean" /> | ||||
|           </vxe-select> | ||||
|         </template> | ||||
|       </vxe-column> | ||||
|       <vxe-column title="java属性" width="8%" field="javaField"> | ||||
|         <template #default="{ row }"> | ||||
|           <vxe-input v-model="row.javaField" placeholder="请输入java属性" /> | ||||
|         </template> | ||||
|       </vxe-column> | ||||
|     </vxe-colgroup> | ||||
|     <vxe-colgroup title="增删改查"> | ||||
|       <vxe-column title="插入" width="40px" field="createOperation"> | ||||
|         <template #default="{ row }"> | ||||
|           <vxe-checkbox true-label="true" false-label="false" v-model="row.createOperation" /> | ||||
|         </template> | ||||
|       </vxe-column> | ||||
|       <vxe-column title="编辑" width="40px" field="updateOperation"> | ||||
|         <template #default="{ row }"> | ||||
|           <vxe-checkbox true-label="true" false-label="false" v-model="row.updateOperation" /> | ||||
|         </template> | ||||
|       </vxe-column> | ||||
|       <vxe-column title="列表" width="40px" field="listOperationResult"> | ||||
|         <template #default="{ row }"> | ||||
|           <vxe-checkbox true-label="true" false-label="false" v-model="row.listOperationResult" /> | ||||
|         </template> | ||||
|       </vxe-column> | ||||
|       <vxe-column title="查询" width="40px" field="listOperation"> | ||||
|         <template #default="{ row }"> | ||||
|           <vxe-checkbox true-label="true" false-label="false" v-model="row.listOperation" /> | ||||
|         </template> | ||||
|       </vxe-column> | ||||
|       <vxe-column title="允许空" width="40px" field="nullable"> | ||||
|         <template #default="{ row }"> | ||||
|           <vxe-checkbox true-label="true" false-label="false" v-model="row.nullable" /> | ||||
|         </template> | ||||
|       </vxe-column> | ||||
|       <vxe-column title="查询方式" width="60px" field="listOperationCondition"> | ||||
|         <template #default="{ row }"> | ||||
|           <vxe-select v-model="row.listOperationCondition" placeholder="请选择查询方式"> | ||||
|             <vxe-option label="=" value="=" /> | ||||
|             <vxe-option label="!=" value="!=" /> | ||||
|             <vxe-option label=">" value=">" /> | ||||
|             <vxe-option label=">=" value=">=" /> | ||||
|             <vxe-option label="<" value="<>" /> | ||||
|             <vxe-option label="<=" value="<=" /> | ||||
|             <vxe-option label="LIKE" value="LIKE" /> | ||||
|             <vxe-option label="BETWEEN" value="BETWEEN" /> | ||||
|           </vxe-select> | ||||
|         </template> | ||||
|       </vxe-column> | ||||
|     </vxe-colgroup> | ||||
|     <vxe-column title="显示类型" width="10%" field="htmlType"> | ||||
|       <template #default="{ row }"> | ||||
|         <el-select v-model="row.htmlType"> | ||||
|           <el-option label="文本框" value="input" /> | ||||
|           <el-option label="文本域" value="textarea" /> | ||||
|           <el-option label="下拉框" value="select" /> | ||||
|           <el-option label="单选框" value="radio" /> | ||||
|           <el-option label="复选框" value="checkbox" /> | ||||
|           <el-option label="日期控件" value="datetime" /> | ||||
|           <el-option label="图片上传" value="imageUpload" /> | ||||
|           <el-option label="文件上传" value="fileUpload" /> | ||||
|           <el-option label="富文本控件" value="editor" /> | ||||
|         </el-select> | ||||
|         <vxe-select v-model="row.htmlType" placeholder="请选择显示类型"> | ||||
|           <vxe-option label="文本框" value="input" /> | ||||
|           <vxe-option label="文本域" value="textarea" /> | ||||
|           <vxe-option label="下拉框" value="select" /> | ||||
|           <vxe-option label="单选框" value="radio" /> | ||||
|           <vxe-option label="复选框" value="checkbox" /> | ||||
|           <vxe-option label="日期控件" value="datetime" /> | ||||
|           <vxe-option label="图片上传" value="imageUpload" /> | ||||
|           <vxe-option label="文件上传" value="fileUpload" /> | ||||
|           <vxe-option label="富文本控件" value="editor" /> | ||||
|         </vxe-select> | ||||
|       </template> | ||||
|     </vxe-column> | ||||
|     <vxe-column title="字典类型" width="10%" field="dictType"> | ||||
|       <template #default="{ row }"> | ||||
|         <el-select v-model="row.dictType" clearable filterable placeholder="请选择"> | ||||
|           <el-option | ||||
|         <vxe-select v-model="row.dictType" clearable filterable placeholder="请选择字典类型"> | ||||
|           <vxe-option | ||||
|             v-for="dict in dictOptions" | ||||
|             :key="dict.id" | ||||
|             :label="dict.name" | ||||
|             :value="dict.type" | ||||
|           /> | ||||
|         </el-select> | ||||
|         </vxe-select> | ||||
|       </template> | ||||
|     </vxe-column> | ||||
|     <vxe-column title="示例" field="example"> | ||||
|       <template #default="{ row }"> | ||||
|         <el-input v-model="row.example" /> | ||||
|         <vxe-input v-model="row.example" placeholder="请输入示例" /> | ||||
|       </template> | ||||
|     </vxe-column> | ||||
|   </vxe-table> | ||||
| </template> | ||||
| <script setup lang="ts"> | ||||
| import { onMounted, PropType, ref } from 'vue' | ||||
| import { ElInput, ElSelect, ElOption } from 'element-plus' | ||||
| import { DictTypeVO } from '@/api/system/dict/types' | ||||
| import { CodegenColumnVO } from '@/api/infra/codegen/types' | ||||
| import { listSimpleDictTypeApi } from '@/api/system/dict/dict.type' | ||||
|  | ||||
| @ -1,135 +0,0 @@ | ||||
| <template> | ||||
|   <Form :rules="rules" @register="register" /> | ||||
| </template> | ||||
| <script setup lang="ts"> | ||||
| import { onMounted, PropType, reactive, ref, watch } from 'vue' | ||||
| import { Form } from '@/components/Form' | ||||
| import { useForm } from '@/hooks/web/useForm' | ||||
| import { required } from '@/utils/formRules' | ||||
| import { handleTree, defaultProps } from '@/utils/tree' | ||||
| import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' | ||||
| import { listSimpleMenusApi } from '@/api/system/menu' | ||||
| import { CodegenTableVO } from '@/api/infra/codegen/types' | ||||
| import { FormSchema } from '@/types/form' | ||||
| const props = defineProps({ | ||||
|   genInfo: { | ||||
|     type: Object as PropType<Nullable<CodegenTableVO>>, | ||||
|     default: () => null | ||||
|   } | ||||
| }) | ||||
| const rules = reactive({ | ||||
|   templateType: [required], | ||||
|   scene: [required], | ||||
|   moduleName: [required], | ||||
|   businessName: [required], | ||||
|   businessPackage: [required], | ||||
|   className: [required], | ||||
|   classComment: [required] | ||||
| }) | ||||
| const templateTypeOptions = getIntDictOptions(DICT_TYPE.INFRA_CODEGEN_TEMPLATE_TYPE) | ||||
| const sceneOptions = getIntDictOptions(DICT_TYPE.INFRA_CODEGEN_SCENE) | ||||
| const menuOptions = ref<any>([]) // 树形结构 | ||||
| const getTree = async () => { | ||||
|   const res = await listSimpleMenusApi() | ||||
|   menuOptions.value = handleTree(res) | ||||
| } | ||||
| const schema = reactive<FormSchema[]>([ | ||||
|   { | ||||
|     label: '生成模板', | ||||
|     field: 'templateType', | ||||
|     component: 'Select', | ||||
|     componentProps: { | ||||
|       options: templateTypeOptions | ||||
|     }, | ||||
|     colProps: { | ||||
|       span: 12 | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     label: '生成场景', | ||||
|     field: 'scene', | ||||
|     component: 'Select', | ||||
|     componentProps: { | ||||
|       options: sceneOptions | ||||
|     }, | ||||
|     colProps: { | ||||
|       span: 12 | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     label: '模块名', | ||||
|     field: 'moduleName', | ||||
|     component: 'Input', | ||||
|     labelMessage: '模块名,即一级目录,例如 system、infra、tool 等等', | ||||
|     colProps: { | ||||
|       span: 12 | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     label: '业务名', | ||||
|     field: 'businessName', | ||||
|     component: 'Input', | ||||
|     labelMessage: '业务名,即二级目录,例如 user、permission、dict 等等', | ||||
|     colProps: { | ||||
|       span: 12 | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     label: '类名称', | ||||
|     field: 'className', | ||||
|     component: 'Input', | ||||
|     labelMessage: '类名称(首字母大写),例如SysUser、SysMenu、SysDictData 等等', | ||||
|     colProps: { | ||||
|       span: 12 | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     label: '类描述', | ||||
|     field: 'classComment', | ||||
|     component: 'Input', | ||||
|     labelMessage: '用作类描述,例如 用户', | ||||
|     colProps: { | ||||
|       span: 12 | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     label: '上级菜单', | ||||
|     field: 'parentMenuId', | ||||
|     component: 'TreeSelect', | ||||
|     componentProps: { | ||||
|       data: menuOptions, | ||||
|       props: defaultProps, | ||||
|       checkStrictly: true, | ||||
|       nodeKey: 'id' | ||||
|     }, | ||||
|     labelMessage: '分配到指定菜单下,例如 系统管理', | ||||
|     colProps: { | ||||
|       span: 12 | ||||
|     } | ||||
|   } | ||||
| ]) | ||||
| const { register, methods, elFormRef } = useForm({ | ||||
|   schema | ||||
| }) | ||||
|  | ||||
| // ========== 初始化 ========== | ||||
| onMounted(async () => { | ||||
|   await getTree() | ||||
| }) | ||||
| watch( | ||||
|   () => props.genInfo, | ||||
|   (genInfo) => { | ||||
|     if (!genInfo) return | ||||
|     const { setValues } = methods | ||||
|     setValues(genInfo) | ||||
|   }, | ||||
|   { | ||||
|     deep: true, | ||||
|     immediate: true | ||||
|   } | ||||
| ) | ||||
| defineExpose({ | ||||
|   elFormRef, | ||||
|   getFormData: methods.getFormData | ||||
| }) | ||||
| </script> | ||||
| @ -1,6 +1,5 @@ | ||||
| import BasicInfoForm from './BasicInfoForm.vue' | ||||
| import CloumInfoForm from './CloumInfoForm.vue' | ||||
| import GenInfoForm from './GenInfoForm.vue' | ||||
| import ImportTable from './ImportTable.vue' | ||||
| import Preview from './Preview.vue' | ||||
| export { BasicInfoForm, CloumInfoForm, GenInfoForm, ImportTable, Preview } | ||||
| export { BasicInfoForm, CloumInfoForm, ImportTable, Preview } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 xingyu
					xingyu