gen.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. from flask import request, send_file
  2. from zipfile import ZipFile
  3. from io import BytesIO
  4. from ruoyi_common.base.model import AjaxResponse, TableResponse
  5. from ruoyi_common.constant import HttpStatus
  6. from ruoyi_common.descriptor.serializer import JsonSerializer
  7. from ruoyi_common.descriptor.validator import QueryValidator, BodyValidator, PathValidator
  8. from ruoyi_framework.descriptor.permission import HasPerm, PreAuthorize
  9. from ruoyi_generator.controller import gen
  10. from ruoyi_generator.domain.entity import GenTable
  11. from ruoyi_generator.domain.po import GenTablePO, GenTableColumnPO
  12. from ruoyi_generator.service import GenTableService
  13. from ruoyi_generator.service.column_service import GenTableColumnService
  14. gen_table_service = GenTableService()
  15. gen_table_column_service = GenTableColumnService()
  16. @gen.route('/list', methods=["GET"])
  17. @QueryValidator(is_page=True)
  18. @PreAuthorize(HasPerm('tool:gen:list'))
  19. @JsonSerializer()
  20. def gen_list(dto: GenTablePO):
  21. """查询代码生成列表"""
  22. gen_table = GenTable()
  23. # 转换PO到Entity对象,只复制存在的字段
  24. for attr in dto.model_fields.keys():
  25. if hasattr(gen_table, attr):
  26. setattr(gen_table, attr, getattr(dto, attr))
  27. tables, total = gen_table_service.select_gen_table_list(gen_table)
  28. return TableResponse(code=HttpStatus.SUCCESS, msg='查询成功', rows=tables, total=total)
  29. @gen.route('/db/list', methods=["GET"])
  30. @QueryValidator(is_page=True)
  31. @PreAuthorize(HasPerm('tool:gen:list'))
  32. @JsonSerializer()
  33. def db_list(dto: GenTablePO):
  34. """查询数据库表列表"""
  35. gen_table = GenTable()
  36. # 转换PO到Entity对象,只复制存在的字段
  37. for attr in dto.model_fields.keys():
  38. if hasattr(gen_table, attr):
  39. setattr(gen_table, attr, getattr(dto, attr))
  40. tables, total = gen_table_service.select_db_table_list(gen_table)
  41. return TableResponse(code=HttpStatus.SUCCESS, msg='查询成功', rows=tables, total=total)
  42. @gen.route('/<int:tableId>', methods=["GET"])
  43. @PathValidator()
  44. @PreAuthorize(HasPerm('tool:gen:query'))
  45. @JsonSerializer()
  46. def get_gen_table(tableId: int):
  47. """查询代码生成详细信息"""
  48. table = gen_table_service.select_gen_table_by_id(tableId)
  49. # 如果表存在但没有字段信息,则尝试从数据库同步
  50. columns, total = gen_table_column_service.select_gen_table_column_list_by_table_id(tableId)
  51. if not columns:
  52. # 尝试同步数据库结构
  53. gen_table_service.synch_db(table.table_name)
  54. # 再次查询字段信息
  55. columns, total = gen_table_column_service.select_gen_table_column_list_by_table_id(tableId)
  56. # 获取所有表名列表
  57. all_tables_result = gen_table_service.select_gen_table_list(GenTable())
  58. all_tables = []
  59. if all_tables_result:
  60. # 确保返回的是完整的表对象而不是仅表名
  61. all_tables = all_tables_result[0]
  62. return AjaxResponse.from_success(data={
  63. 'info': table,
  64. 'rows': columns,
  65. 'tables': all_tables
  66. })
  67. @gen.route('/', methods=['POST'])
  68. @BodyValidator()
  69. @PreAuthorize(HasPerm('tool:gen:add'))
  70. @JsonSerializer()
  71. def add_gen_table(dto: GenTablePO):
  72. """新增代码生成表"""
  73. gen_table = GenTable()
  74. # 转换PO到Entity对象,只复制存在的字段
  75. for attr in dto.model_fields.keys():
  76. if hasattr(gen_table, attr):
  77. setattr(gen_table, attr, getattr(dto, attr))
  78. # 实现新增逻辑
  79. table_id = gen_table_service.insert_gen_table(gen_table)
  80. if table_id > 0:
  81. return AjaxResponse.from_success(msg='新增成功')
  82. else:
  83. return AjaxResponse.from_error(msg='新增失败')
  84. @gen.route('/importTable', methods=['POST'])
  85. @PreAuthorize(HasPerm('tool:gen:import'))
  86. @JsonSerializer()
  87. def import_table():
  88. """导入表结构"""
  89. tables = request.args.get('tables')
  90. if not tables:
  91. return AjaxResponse.from_error(msg='参数错误')
  92. table_list = [table.strip() for table in tables.split(',') if table.strip()]
  93. if not table_list:
  94. return AjaxResponse.from_error(msg='参数错误')
  95. gen_table_service.import_gen_table(table_list)
  96. return AjaxResponse.from_success(msg='导入成功')
  97. @gen.route('/<int:tableId>', methods=['PUT'])
  98. @BodyValidator()
  99. @PreAuthorize(HasPerm('tool:gen:edit'))
  100. @JsonSerializer()
  101. def update_gen_table(dto: GenTablePO):
  102. print(dto)
  103. """修改保存代码生成信息"""
  104. gen_table = GenTable()
  105. # 设置表ID
  106. gen_table.table_id = dto.table_id
  107. # 从请求数据中设置属性
  108. for attr in dto.model_fields.keys():
  109. if hasattr(gen_table, attr):
  110. setattr(gen_table, attr, getattr(dto, attr))
  111. # 处理 options 字段和 parentMenuId
  112. import json
  113. options_dict = {}
  114. # 如果 options 字段存在,先解析它
  115. if hasattr(dto, 'options') and dto.options:
  116. try:
  117. if isinstance(dto.options, str):
  118. options_dict = json.loads(dto.options)
  119. else:
  120. options_dict = dto.options.copy() if hasattr(dto.options, 'copy') else dto.options
  121. except Exception as e:
  122. print(f"解析 options 字段出错: {e}")
  123. options_dict = {}
  124. # 检查 params 中是否有 parentMenuId(前端可能通过 params 传递)
  125. if hasattr(dto, 'params') and dto.params:
  126. if isinstance(dto.params, dict) and 'parentMenuId' in dto.params:
  127. options_dict['parentMenuId'] = dto.params.get('parentMenuId')
  128. # 如果 options_dict 中有 parentMenuId,更新 options 字段
  129. if 'parentMenuId' in options_dict:
  130. gen_table.options = json.dumps(options_dict, ensure_ascii=False)
  131. gen_table.parent_menu_id = options_dict.get('parentMenuId')
  132. print(f"设置 parentMenuId: {options_dict.get('parentMenuId')}, options: {gen_table.options}")
  133. elif options_dict:
  134. # 即使没有 parentMenuId,也要保存其他 options
  135. gen_table.options = json.dumps(options_dict, ensure_ascii=False)
  136. # 特别处理columns字段
  137. if hasattr(dto, 'columns') and dto.columns is not None:
  138. print(dto.columns)
  139. # 前端传过来的已经是正确的字符串格式,直接使用
  140. gen_table.columns = dto.columns
  141. else:
  142. gen_table.columns = dto.columns
  143. gen_table_service.update_gen_table(gen_table)
  144. return AjaxResponse.from_success(msg='修改成功')
  145. @gen.route('/<tableIds>', methods=['DELETE'])
  146. @PathValidator()
  147. @PreAuthorize(HasPerm('tool:gen:remove'))
  148. @JsonSerializer()
  149. def delete_gen_table(tableIds: str):
  150. """删除代码生成表"""
  151. try:
  152. table_ids = [int(id) for id in tableIds.split(',')]
  153. gen_table_service.delete_gen_table_by_ids(table_ids)
  154. return AjaxResponse.from_success(msg='删除成功')
  155. except Exception as e:
  156. return AjaxResponse.from_error(msg=f'删除失败: {str(e)}')
  157. @gen.route('/preview/<int:tableId>', methods=["GET"])
  158. @PathValidator()
  159. @PreAuthorize(HasPerm('tool:gen:preview'))
  160. @JsonSerializer()
  161. def preview(tableId: int):
  162. """预览代码"""
  163. try:
  164. data = gen_table_service.preview_code(tableId)
  165. return AjaxResponse.from_success(data=data)
  166. except Exception as e:
  167. return AjaxResponse.from_error(msg=f'预览失败: {str(e)}')
  168. @gen.route('/download/<table_name>', methods=["GET"])
  169. @PathValidator()
  170. @PreAuthorize(HasPerm('tool:gen:code'))
  171. @JsonSerializer()
  172. def download(table_name: str):
  173. """生成代码(下载方式)"""
  174. try:
  175. data = gen_table_service.generator_code(table_name)
  176. return send_file(
  177. BytesIO(data), # 将bytes包装成BytesIO对象
  178. mimetype='application/zip',
  179. as_attachment=True,
  180. download_name=f'{table_name}.zip'
  181. )
  182. except Exception as e:
  183. return AjaxResponse.from_error(msg=f'生成失败: {str(e)}')
  184. @gen.route('/genCode/<table_name>', methods=["GET"])
  185. @PathValidator()
  186. @PreAuthorize(HasPerm('tool:gen:code'))
  187. @JsonSerializer()
  188. def gen_code(table_name: str):
  189. """生成代码(自定义路径)"""
  190. try:
  191. data = gen_table_service.generator_code(table_name)
  192. return send_file(
  193. BytesIO(data), # 将bytes包装成BytesIO对象
  194. mimetype='application/zip',
  195. as_attachment=True,
  196. download_name=f'{table_name}.zip'
  197. )
  198. except Exception as e:
  199. return AjaxResponse.from_error(msg=f'生成失败: {str(e)}')
  200. @gen.route('/batchGenCode', methods=["GET"])
  201. @PreAuthorize(HasPerm('tool:gen:code'))
  202. @JsonSerializer()
  203. def batch_gen_code():
  204. """批量生成代码"""
  205. try:
  206. tables = request.args.get('tables')
  207. if not tables:
  208. return AjaxResponse.from_error(msg='参数错误')
  209. table_list = [table.strip() for table in tables.split(',') if table.strip()]
  210. if not table_list:
  211. return AjaxResponse.from_error(msg='参数错误')
  212. # 生成代码
  213. data = gen_table_service.batch_generator_code(table_list)
  214. return send_file(
  215. BytesIO(data), # 将bytes包装成BytesIO对象
  216. mimetype='application/zip',
  217. as_attachment=True,
  218. download_name='code.zip'
  219. )
  220. except Exception as e:
  221. return AjaxResponse.from_error(msg=f'批量生成失败: {str(e)}')
  222. @gen.route('/synchDb/<table_name>', methods=["GET"])
  223. @PreAuthorize(HasPerm('tool:gen:edit'))
  224. @JsonSerializer()
  225. def synch_db(table_name):
  226. """同步数据库"""
  227. # 检查表名是否有效
  228. if not table_name or table_name.lower() == 'null':
  229. return AjaxResponse.from_error(msg='表名不能为空')
  230. try:
  231. result = gen_table_service.synch_db(table_name)
  232. if result:
  233. return AjaxResponse.from_success(msg='同步成功')
  234. else:
  235. return AjaxResponse.from_error(msg='同步失败')
  236. except Exception as e:
  237. return AjaxResponse.from_error(msg=f'同步失败: {str(e)}')
  238. @gen.route('/column/list', methods=["GET"])
  239. @QueryValidator(is_page=True)
  240. @PreAuthorize(HasPerm('tool:gen:list'))
  241. @JsonSerializer()
  242. def column_list(dto: GenTableColumnPO):
  243. """查询数据库表字段列表"""
  244. table_id = request.args.get('tableId')
  245. if table_id:
  246. columns, total = gen_table_column_service.select_gen_table_column_list_by_table_id(int(table_id))
  247. else:
  248. columns, total = [], 0
  249. return TableResponse(code=HttpStatus.SUCCESS, msg='查询成功', rows=columns, total=total)
  250. @gen.route('/export', methods=["GET"])
  251. @PreAuthorize(HasPerm('tool:gen:export'))
  252. @JsonSerializer()
  253. def export():
  254. """导出代码生成表数据"""
  255. try:
  256. tables, total = gen_table_service.select_gen_table_list(GenTable())
  257. return AjaxResponse.from_success(data=tables, msg='导出成功')
  258. except Exception as e:
  259. return AjaxResponse.from_error(msg=f'导出失败: {str(e)}')
  260. @gen.route('/tableInfo/<table_name>', methods=["GET"])
  261. @PathValidator()
  262. @PreAuthorize(HasPerm('tool:gen:list'))
  263. @JsonSerializer()
  264. def get_table_info(table_name: str):
  265. """获取表信息"""
  266. try:
  267. if not gen_table_service.validate_table_name(table_name):
  268. return AjaxResponse.from_error(msg='表名格式不正确')
  269. table_info = gen_table_service.get_table_info(table_name)
  270. return AjaxResponse.from_success(data=table_info)
  271. except Exception as e:
  272. return AjaxResponse.from_error(msg=f'获取表信息失败: {str(e)}')