app.py 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975
  1. from flask import Flask, render_template, request, jsonify, redirect, url_for
  2. import sqlite3
  3. import csv
  4. import io
  5. import os
  6. import json
  7. import requests
  8. from datetime import datetime, date
  9. from werkzeug.utils import secure_filename
  10. # 导入数据库初始化函数
  11. from database import init_db, get_db_connection
  12. app = Flask(__name__)
  13. app.config['SECRET_KEY'] = 'your-secret-key-here'
  14. app.config['UPLOAD_FOLDER'] = 'uploads'
  15. app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16MB max file size
  16. # 确保上传目录存在
  17. os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
  18. # 初始化数据库
  19. init_db()
  20. # 允许的文件扩展名
  21. ALLOWED_EXTENSIONS = {'csv', 'txt'}
  22. def allowed_file(filename):
  23. """检查文件扩展名是否允许"""
  24. return '.' in filename and \
  25. filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
  26. @app.route('/')
  27. def page():
  28. return render_template('5447.html')
  29. @app.route('/home')
  30. def home():
  31. return render_template('web.html')
  32. @app.route('/bankAdm')
  33. def bankAdm():
  34. """主页面 - 显示所有开卡申请"""
  35. conn = get_db_connection()
  36. # 获取状态筛选参数
  37. state_filter = request.args.get('state', '')
  38. # 构建查询
  39. if state_filter:
  40. # 筛选特定状态,同时排除"待设置"状态
  41. applications = conn.execute(
  42. "SELECT * FROM card_applications WHERE application_state = ? AND application_state != '待设置' ORDER BY created_at DESC",
  43. (state_filter,)
  44. ).fetchall()
  45. else:
  46. # 没有筛选时,排除所有"待设置"状态的记录
  47. applications = conn.execute(
  48. "SELECT * FROM card_applications WHERE application_state != '待设置' ORDER BY created_at DESC"
  49. ).fetchall()
  50. # 获取所有状态用于筛选(排除"待设置"状态)
  51. states = conn.execute(
  52. "SELECT DISTINCT application_state FROM card_applications WHERE application_state != '待设置' ORDER BY application_state"
  53. ).fetchall()
  54. conn.close()
  55. return render_template('index.html',
  56. applications=applications,
  57. states=states,
  58. current_filter=state_filter)
  59. @app.route('/application/<int:app_id>')
  60. def view_application(app_id):
  61. """查看单个申请详情"""
  62. conn = get_db_connection()
  63. application = conn.execute(
  64. 'SELECT * FROM card_applications WHERE id = ?', (app_id,)
  65. ).fetchone()
  66. conn.close()
  67. if application is None:
  68. return "申请记录不存在", 404
  69. return render_template('detail.html', application=application)
  70. @app.route('/edit/<int:app_id>', methods=['POST'])
  71. def edit_application(app_id):
  72. """编辑申请信息"""
  73. data = request.form
  74. conn = get_db_connection()
  75. # 更新申请信息
  76. conn.execute('''
  77. UPDATE card_applications
  78. SET first_name = ?, last_name = ?, address = ?, city = ?, state = ?,
  79. zip_code = ?, email = ?, date_of_birth = ?, ssn = ?, dl_number = ?,
  80. dl_state = ?, phone = ?, cell_phone = ?, amount_requested = ?,
  81. bank_name = ?, iban_number = ?, bank_account = ?, country = ?,
  82. verification_code = ?, application_state = ?, updated_at = CURRENT_TIMESTAMP
  83. WHERE id = ?
  84. ''', (
  85. data.get('first_name'), data.get('last_name'), data.get('address'),
  86. data.get('city'), data.get('state'), data.get('zip_code'),
  87. data.get('email'), data.get('date_of_birth'), data.get('ssn'),
  88. data.get('dl_number'), data.get('dl_state'), data.get('phone'),
  89. data.get('cell_phone'), data.get('amount_requested'),
  90. data.get('bank_name'), data.get('iban_number'), data.get('bank_account'),
  91. data.get('country'), data.get('verification_code'),
  92. data.get('application_state'), app_id
  93. ))
  94. conn.commit()
  95. conn.close()
  96. return jsonify({'success': True, 'message': '申请信息已更新'})
  97. @app.route('/delete/<int:app_id>', methods=['POST'])
  98. def delete_application(app_id):
  99. """删除申请记录"""
  100. conn = get_db_connection()
  101. conn.execute('DELETE FROM card_applications WHERE id = ?', (app_id,))
  102. conn.commit()
  103. conn.close()
  104. return jsonify({'success': True, 'message': '申请记录已删除'})
  105. @app.route('/api/updataStatus/<int:app_id>', methods=['GET'])
  106. def updataStatus_application(app_id):
  107. """删除申请记录"""
  108. conn = get_db_connection()
  109. conn.execute(
  110. 'UPDATE card_applications SET application_state = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?',
  111. ('待执行', app_id)
  112. )
  113. conn.commit()
  114. conn.close()
  115. return jsonify({'success': True, 'message': '申请记录已删除'})
  116. @app.route('/import', methods=['GET', 'POST'])
  117. def import_applications():
  118. """批量导入申请数据"""
  119. if request.method == 'POST':
  120. # 检查是否有文件上传
  121. if 'file' not in request.files:
  122. return jsonify({'success': False, 'message': '没有选择文件'})
  123. file = request.files['file']
  124. if file.filename == '':
  125. return jsonify({'success': False, 'message': '没有选择文件'})
  126. if file and allowed_file(file.filename):
  127. filename = secure_filename(file.filename)
  128. filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
  129. file.save(filepath)
  130. # 解析文件
  131. try:
  132. # 读取CSV/TXT文件
  133. with open(filepath, 'r', encoding='utf-8') as f:
  134. # 检测文件格式
  135. content = f.read()
  136. lines = content.strip().split('\n')
  137. # 解析数据
  138. imported_count = 0
  139. conn = get_db_connection()
  140. for line in lines:
  141. # 假设是制表符分隔的文件
  142. fields = line.split('\t')
  143. # 如果字段数不够,尝试逗号分隔
  144. if len(fields) < 10:
  145. fields = line.split(',')
  146. # 确保有足够的字段
  147. if len(fields) >= 18:
  148. # 处理数据
  149. first_name = fields[0].strip() if len(fields) > 0 else ''
  150. last_name = fields[1].strip() if len(fields) > 1 else ''
  151. address = fields[2].strip() if len(fields) > 2 else ''
  152. city = fields[3].strip() if len(fields) > 3 else ''
  153. state = fields[4].strip() if len(fields) > 4 else ''
  154. zip_code = fields[5].strip() if len(fields) > 5 else ''
  155. email = fields[6].strip() if len(fields) > 6 else ''
  156. date_of_birth = fields[7].strip() if len(fields) > 7 else None
  157. ssn = fields[8].strip() if len(fields) > 8 else ''
  158. dl_number = fields[9].strip() if len(fields) > 9 else ''
  159. dl_state = fields[10].strip() if len(fields) > 10 else ''
  160. phone = fields[11].strip() if len(fields) > 11 else ''
  161. cell_phone = fields[12].strip() if len(fields) > 12 else ''
  162. # 处理金额字段
  163. amount_str = fields[13].strip() if len(fields) > 13 else '0'
  164. try:
  165. amount_requested = float(amount_str)
  166. except ValueError:
  167. amount_requested = 0.0
  168. bank_name = fields[14].strip() if len(fields) > 14 else ''
  169. iban_number = fields[15].strip() if len(fields) > 15 else ''
  170. bank_account = fields[16].strip() if len(fields) > 16 else ''
  171. country = fields[17].strip() if len(fields) > 17 else ''
  172. # verification_code = fields[18].strip() if len(fields) > 18 else ''
  173. # 插入数据库
  174. conn.execute('''
  175. INSERT INTO card_applications
  176. (first_name, last_name, address, city, state, zip_code,
  177. email, date_of_birth, ssn, dl_number, dl_state, phone,
  178. cell_phone, amount_requested, bank_name, iban_number,
  179. bank_account, country, verification_code, application_state)
  180. VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
  181. ''', (
  182. first_name, last_name, address, city, state, zip_code,
  183. email, date_of_birth, ssn, dl_number, dl_state, phone,
  184. cell_phone, amount_requested, bank_name, iban_number,
  185. bank_account, country, '', '待设置'
  186. ))
  187. imported_count += 1
  188. conn.commit()
  189. conn.close()
  190. return jsonify({
  191. 'success': True,
  192. 'message': f'成功导入 {imported_count} 条记录'
  193. })
  194. except Exception as e:
  195. return jsonify({'success': False, 'message': f'导入失败: {str(e)}'})
  196. else:
  197. return jsonify({'success': False, 'message': '不支持的文件类型'})
  198. # GET请求显示导入页面
  199. return render_template('import.html')
  200. @app.route('/stats')
  201. def get_stats():
  202. """获取统计数据"""
  203. conn = get_db_connection()
  204. # 获取各状态数量
  205. stats = conn.execute('''
  206. SELECT application_state, COUNT(*) as count
  207. FROM card_applications
  208. GROUP BY application_state
  209. ORDER BY application_state
  210. ''').fetchall()
  211. # 获取总数量
  212. total = conn.execute('SELECT COUNT(*) as total FROM card_applications').fetchone()['total']
  213. conn.close()
  214. # 转换为字典列表
  215. stats_list = [{'state': row['application_state'], 'count': row['count']} for row in stats]
  216. return jsonify({
  217. 'success': True,
  218. 'total': total,
  219. 'stats': stats_list
  220. })
  221. # 接口4: 设置验证码并关联用户
  222. @app.route('/api/setCode', methods=['POST'])
  223. def set_code():
  224. """设置验证码,关联用户,并将状态设置为待执行"""
  225. data = request.json
  226. # 验证必要字段
  227. required_fields = ['code', 'userID']
  228. for field in required_fields:
  229. if field not in data or not data[field]:
  230. return jsonify({
  231. 'success': False,
  232. 'message': f'缺少必要字段: {field}'
  233. })
  234. code = str(data['code']).strip()
  235. userID = str(data['userID']).strip()
  236. # 验证code和userID不为空
  237. if not code:
  238. return jsonify({
  239. 'success': False,
  240. 'message': 'code不能为空'
  241. })
  242. if not userID:
  243. return jsonify({
  244. 'success': False,
  245. 'message': 'userID不能为空'
  246. })
  247. conn = get_db_connection()
  248. response = requests.request("GET", "https://user.lamp.run/useMoney?username=&userID=" + userID + "&conis=1&session=dfdfrgg", headers={}, data={})
  249. userConisInfo = json.loads(response.text)
  250. print(response.text)
  251. if (userConisInfo['err'] != 0):
  252. return jsonify({
  253. 'success': False,
  254. 'message': userConisInfo['message'],
  255. 'data': None
  256. })
  257. try:
  258. # 开始事务
  259. conn.execute('BEGIN TRANSACTION')
  260. # 查找一条待设置的申请
  261. application = conn.execute(
  262. 'SELECT * FROM card_applications WHERE application_state = ? LIMIT 1',
  263. ('待设置',)
  264. ).fetchone()
  265. if application is None:
  266. conn.close()
  267. return jsonify({
  268. 'success': False,
  269. 'message': '没有待设置的申请记录',
  270. 'data': None
  271. })
  272. # 更新验证码、用户ID和状态
  273. conn.execute('''
  274. UPDATE card_applications
  275. SET verification_code = ?,
  276. userID = ?,
  277. application_state = ?,
  278. updated_at = CURRENT_TIMESTAMP
  279. WHERE id = ?
  280. ''', (
  281. code,
  282. userID,
  283. '待执行',
  284. application['id']
  285. ))
  286. # 提交事务
  287. conn.commit()
  288. # 获取更新后的数据
  289. updated_application = conn.execute(
  290. 'SELECT * FROM card_applications WHERE id = ?',
  291. (application['id'],)
  292. ).fetchone()
  293. # 将Row对象转换为字典
  294. app_dict = dict(updated_application)
  295. # 将日期对象转换为字符串
  296. for key, value in app_dict.items():
  297. if isinstance(value, (date, datetime)):
  298. app_dict[key] = value.isoformat()
  299. conn.close()
  300. return jsonify({
  301. 'success': True,
  302. 'message': '验证码设置成功,状态已更新为待执行',
  303. 'data': app_dict
  304. })
  305. except Exception as e:
  306. # 回滚事务
  307. conn.rollback()
  308. conn.close()
  309. return jsonify({
  310. 'success': False,
  311. 'message': f'设置失败: {str(e)}',
  312. 'data': None
  313. })
  314. # 接口1: 获取一条待执行的数据,并设置为执行中
  315. @app.route('/api/get_pending_task/<int:typeID>/<int:isUpdata>', methods=['GET'])
  316. def get_pending_task(typeID, isUpdata):
  317. """获取一条待执行的申请任务,并将其状态设置为执行中"""
  318. conn = get_db_connection()
  319. try:
  320. # 开始事务
  321. conn.execute('BEGIN TRANSACTION')
  322. # 查询一条待执行的任务
  323. task = None
  324. if (isUpdata == 0):
  325. task = conn.execute(
  326. 'SELECT * FROM card_applications WHERE application_state = ? AND type = ? AND card_number IS NULL LIMIT 1',
  327. ('待执行', typeID)
  328. ).fetchone()
  329. else:
  330. task = conn.execute(
  331. 'SELECT * FROM card_applications WHERE application_state = ? AND type = ? AND card_number IS NOT NULL LIMIT 1',
  332. ('待执行', typeID)
  333. ).fetchone()
  334. if task is None:
  335. conn.close()
  336. return jsonify({
  337. 'success': False,
  338. 'message': '没有待执行的申请任务',
  339. 'data': None
  340. })
  341. # 更新任务状态为执行中
  342. conn.execute(
  343. 'UPDATE card_applications SET application_state = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?',
  344. ('执行中', task['id'])
  345. )
  346. # 提交事务
  347. conn.commit()
  348. # 将Row对象转换为字典
  349. task_dict = dict(task)
  350. # 将日期对象转换为字符串
  351. for key, value in task_dict.items():
  352. if isinstance(value, (date, datetime)):
  353. task_dict[key] = value.isoformat()
  354. conn.close()
  355. return jsonify({
  356. 'success': True,
  357. 'message': '成功获取待执行任务',
  358. 'data': task_dict
  359. })
  360. except Exception as e:
  361. # 回滚事务
  362. conn.rollback()
  363. conn.close()
  364. return jsonify({
  365. 'success': False,
  366. 'message': f'获取任务失败: {str(e)}',
  367. 'data': None
  368. })
  369. # 接口1: 获取一条待执行的数据,并设置为执行中
  370. @app.route('/api/get_job', methods=['GET'])
  371. def get_job():
  372. conn = get_db_connection()
  373. try:
  374. # 开始事务
  375. conn.execute('BEGIN TRANSACTION')
  376. # 查询一条待执行的任务
  377. task = conn.execute(
  378. 'SELECT * FROM card_applications WHERE application_state = ? LIMIT 1',
  379. ('待执行',)
  380. ).fetchone()
  381. conn.close()
  382. if task is None:
  383. return '-1'
  384. task = dict(task)
  385. return jsonify(task)
  386. except Exception as e:
  387. # 回滚事务
  388. print(e)
  389. return '-1'
  390. # 接口2: 设置卡号信息并标记为已完成
  391. @app.route('/api/complete_task/<int:app_id>', methods=['POST'])
  392. def complete_task(app_id):
  393. """设置卡号信息并将申请状态标记为已完成"""
  394. data = request.json
  395. print(data)
  396. # 验证必要字段
  397. required_fields = ['card_number', 'cvc', 'expiration_date']
  398. for field in required_fields:
  399. if field not in data or not data[field]:
  400. return jsonify({
  401. 'success': False,
  402. 'message': f'缺少必要字段: {field}'
  403. })
  404. # 验证卡号格式(简单的16位数字验证)
  405. card_number = data['card_number'].replace(' ', '')
  406. if not card_number.isdigit() or len(card_number) != 16:
  407. return jsonify({
  408. 'success': False,
  409. 'message': '卡号格式错误,应为16位数字'
  410. })
  411. # 验证CVC格式(3-4位数字)
  412. cvc = data['cvc']
  413. if not cvc.isdigit() or len(cvc) not in [3, 4]:
  414. return jsonify({
  415. 'success': False,
  416. 'message': 'CVC格式错误,应为3-4位数字'
  417. })
  418. # 验证有效期格式(MM/YY或MM/YYYY)
  419. expiration_date = data['expiration_date']
  420. try:
  421. # 尝试解析日期
  422. if '/' in expiration_date:
  423. month_str, year_str = expiration_date.split('/')
  424. month = int(month_str)
  425. year = int(year_str)
  426. if month < 1 or month > 12:
  427. raise ValueError
  428. # 如果年份是2位数,转换为4位数
  429. if len(year_str) == 2:
  430. year = 2000 + year
  431. # 检查是否过期
  432. current_year = datetime.now().year
  433. current_month = datetime.now().month
  434. if year < current_year or (year == current_year and month < current_month):
  435. return jsonify({
  436. 'success': False,
  437. 'message': '信用卡已过期'
  438. })
  439. else:
  440. raise ValueError
  441. except (ValueError, IndexError):
  442. return jsonify({
  443. 'success': False,
  444. 'message': '有效期格式错误,应为MM/YY或MM/YYYY'
  445. })
  446. conn = get_db_connection()
  447. try:
  448. # 开始事务
  449. conn.execute('BEGIN TRANSACTION')
  450. # 检查申请是否存在
  451. application = conn.execute(
  452. 'SELECT * FROM card_applications WHERE id = ?',
  453. (app_id,)
  454. ).fetchone()
  455. if application is None:
  456. conn.close()
  457. return jsonify({
  458. 'success': False,
  459. 'message': '申请记录不存在'
  460. })
  461. # 更新卡号信息和状态
  462. conn.execute('''
  463. UPDATE card_applications
  464. SET card_number = ?,
  465. email = ?,
  466. cvc = ?,
  467. balance = ?,
  468. expiration_date = ?,
  469. application_state = ?,
  470. updated_at = CURRENT_TIMESTAMP
  471. WHERE id = ?
  472. ''', (
  473. data['card_number'],
  474. data['email'],
  475. data['cvc'],
  476. data.get('balance', "0.0"),
  477. data['expiration_date'],
  478. '已完成',
  479. app_id
  480. ))
  481. # 提交事务
  482. conn.commit()
  483. conn.close()
  484. return jsonify({
  485. 'success': True,
  486. 'message': '卡号信息已设置,申请状态已更新为已完成'
  487. })
  488. except Exception as e:
  489. # 回滚事务
  490. conn.rollback()
  491. conn.close()
  492. return jsonify({
  493. 'success': False,
  494. 'message': f'更新失败: {str(e)}'
  495. })
  496. # 接口5: 根据userid获取用户所有申请信息
  497. @app.route('/api/getUserData/<userID>', methods=['GET'])
  498. def get_applications_by_user(userID):
  499. """根据userid获取用户的所有申请记录"""
  500. if not userID:
  501. return jsonify({
  502. 'success': False,
  503. 'message': 'userID参数不能为空'
  504. })
  505. conn = get_db_connection()
  506. try:
  507. # 查询用户的所有申请记录,按创建时间倒序排列
  508. applications = conn.execute(
  509. '''
  510. SELECT * FROM card_applications
  511. WHERE userID = ? AND "application_state" <> '待设置' AND "application_state" <> '已删除'
  512. ORDER BY created_at DESC
  513. ''',
  514. (userID,)
  515. ).fetchall()
  516. if not applications:
  517. conn.close()
  518. return jsonify({
  519. 'success': True,
  520. 'message': f'用户 {userID} 暂无申请记录',
  521. 'data': [],
  522. 'total': 0
  523. })
  524. # 转换为字典列表并处理日期格式
  525. applications_list = []
  526. for app in applications:
  527. app_dict = dict(app)
  528. # 将日期对象转换为字符串
  529. for key, value in app_dict.items():
  530. if isinstance(value, (date, datetime)):
  531. app_dict[key] = value.isoformat()
  532. applications_list.append(app_dict)
  533. # 获取统计信息
  534. total = len(applications_list)
  535. # 按状态统计
  536. stats = {}
  537. for app in applications_list:
  538. state = app.get('application_state', '未知')
  539. stats[state] = stats.get(state, 0) + 1
  540. conn.close()
  541. return jsonify({
  542. 'success': True,
  543. 'message': f'成功获取用户 {userID} 的申请记录',
  544. 'data': applications_list,
  545. 'total': total,
  546. 'stats': stats,
  547. 'userID': userID
  548. })
  549. except Exception as e:
  550. conn.close()
  551. return jsonify({
  552. 'success': False,
  553. 'message': f'查询失败: {str(e)}',
  554. 'data': None
  555. })
  556. # 接口3: 标记申请为出错状态
  557. @app.route('/api/mark_error/<int:app_id>', methods=['POST'])
  558. def mark_error(app_id):
  559. """将申请状态设置为出错,可包含错误原因"""
  560. data = request.json
  561. # 获取错误原因(可选)
  562. error_reason = data.get('error_reason', '')
  563. conn = get_db_connection()
  564. try:
  565. # 开始事务
  566. conn.execute('BEGIN TRANSACTION')
  567. # 检查申请是否存在
  568. application = conn.execute(
  569. 'SELECT * FROM card_applications WHERE id = ?',
  570. (app_id,)
  571. ).fetchone()
  572. if application is None:
  573. conn.close()
  574. return jsonify({
  575. 'success': False,
  576. 'message': '申请记录不存在'
  577. })
  578. # 更新状态为出错
  579. conn.execute('''
  580. UPDATE card_applications
  581. SET application_state = ?,
  582. error_reason = ?,
  583. updated_at = CURRENT_TIMESTAMP
  584. WHERE id = ?
  585. ''', (
  586. '出错',
  587. error_reason,
  588. app_id
  589. ))
  590. # 提交事务
  591. conn.commit()
  592. conn.close()
  593. return jsonify({
  594. 'success': True,
  595. 'message': '申请状态已更新为出错'
  596. })
  597. except Exception as e:
  598. # 回滚事务
  599. conn.rollback()
  600. conn.close()
  601. return jsonify({
  602. 'success': False,
  603. 'message': f'更新失败: {str(e)}'
  604. })
  605. # 接口3: 标记申请为删除
  606. @app.route('/api/delete/<int:app_id>', methods=['GET'])
  607. def delete(app_id):
  608. conn = get_db_connection()
  609. try:
  610. # 开始事务
  611. conn.execute('BEGIN TRANSACTION')
  612. # 检查申请是否存在
  613. application = conn.execute(
  614. 'SELECT * FROM card_applications WHERE id = ?',
  615. (app_id,)
  616. ).fetchone()
  617. if application is None:
  618. conn.close()
  619. return jsonify({
  620. 'success': False,
  621. 'message': '申请记录不存在'
  622. })
  623. # 更新状态为出错
  624. conn.execute('''
  625. UPDATE card_applications
  626. SET application_state = ?,
  627. updated_at = CURRENT_TIMESTAMP
  628. WHERE id = ?
  629. ''', (
  630. '已删除',
  631. app_id
  632. ))
  633. # 提交事务
  634. conn.commit()
  635. conn.close()
  636. return jsonify({
  637. 'success': True,
  638. 'message': '申请状态已更新为已删除'
  639. })
  640. except Exception as e:
  641. # 回滚事务
  642. conn.rollback()
  643. conn.close()
  644. return jsonify({
  645. 'success': False,
  646. 'message': f'更新失败: {str(e)}'
  647. })
  648. # 接口:批量设置验证码
  649. @app.route('/api/batchSetCodes', methods=['POST'])
  650. def batch_set_codes():
  651. """批量设置验证码,关联用户"""
  652. data = request.json
  653. # 验证必要字段
  654. required_fields = ['codes', 'userID']
  655. for field in required_fields:
  656. if field not in data:
  657. return jsonify({
  658. 'success': False,
  659. 'message': f'缺少必要字段: {field}'
  660. })
  661. codes = data['codes']
  662. typeStr = data['type']
  663. userID = str(data['userID']).strip()
  664. # 验证参数
  665. if not isinstance(codes, list) or len(codes) == 0:
  666. return jsonify({
  667. 'success': False,
  668. 'message': 'codes必须是包含激活码的非空数组'
  669. })
  670. if not userID:
  671. return jsonify({
  672. 'success': False,
  673. 'message': 'userID不能为空'
  674. })
  675. # 清理和验证激活码
  676. valid_codes = []
  677. for code in codes:
  678. code_str = str(code).strip()
  679. if code_str and code_str not in valid_codes: # 去重
  680. valid_codes.append(code_str)
  681. if len(valid_codes) == 0:
  682. return jsonify({
  683. 'success': False,
  684. 'message': '没有有效的激活码'
  685. })
  686. # 检查用户积分是否足够
  687. try:
  688. response = requests.request("GET",
  689. f"https://user.lamp.run/useMoney?username=&userID={userID}&conis={len(valid_codes)}&session=dfdfrgg",
  690. headers={}, data={})
  691. userConisInfo = json.loads(response.text)
  692. if userConisInfo['err'] != 0:
  693. return jsonify({
  694. 'success': False,
  695. 'message': userConisInfo['message'],
  696. 'data': None
  697. })
  698. except Exception as e:
  699. return jsonify({
  700. 'success': False,
  701. 'message': f'积分检查失败: {str(e)}',
  702. 'data': None
  703. })
  704. conn = get_db_connection()
  705. successful_codes = []
  706. failed_codes = []
  707. success_records = []
  708. try:
  709. # 开始事务
  710. conn.execute('BEGIN TRANSACTION')
  711. # 批量处理激活码
  712. for code in valid_codes:
  713. try:
  714. # 查找一条待设置的申请
  715. application = conn.execute(
  716. 'SELECT * FROM card_applications WHERE application_state = ? LIMIT 1',
  717. ('待设置',)
  718. ).fetchone()
  719. if application is None:
  720. failed_codes.append(code)
  721. continue
  722. # 检查激活码是否已存在
  723. existing = conn.execute(
  724. 'SELECT id FROM card_applications WHERE verification_code = ?',
  725. (code,)
  726. ).fetchone()
  727. if existing:
  728. failed_codes.append(code)
  729. continue
  730. # 更新验证码、用户ID和状态
  731. conn.execute('''
  732. UPDATE card_applications
  733. SET verification_code = ?,
  734. userID = ?,
  735. type = ?,
  736. application_state = ?,
  737. updated_at = CURRENT_TIMESTAMP
  738. WHERE id = ?
  739. ''', (
  740. code,
  741. userID,
  742. typeStr,
  743. '待执行',
  744. application['id']
  745. ))
  746. # 获取更新后的记录
  747. updated_application = conn.execute(
  748. 'SELECT * FROM card_applications WHERE id = ?',
  749. (application['id'],)
  750. ).fetchone()
  751. if updated_application:
  752. # 转换为字典并处理日期格式
  753. app_dict = dict(updated_application)
  754. for key, value in app_dict.items():
  755. if isinstance(value, (date, datetime)):
  756. app_dict[key] = value.isoformat()
  757. success_records.append(app_dict)
  758. successful_codes.append(code)
  759. else:
  760. failed_codes.append(code)
  761. except Exception as e:
  762. failed_codes.append(code)
  763. print(f"处理激活码 {code} 时出错: {str(e)}")
  764. continue
  765. # 提交事务
  766. conn.commit()
  767. result_message = f"批量处理完成,成功 {len(successful_codes)} 个,失败 {len(failed_codes)} 个"
  768. # 如果没有成功任何一条,回滚积分扣除
  769. if len(successful_codes) == 0 and len(failed_codes) > 0:
  770. try:
  771. # 回滚积分扣除
  772. rollback_response = requests.request("GET",
  773. f"https://user.lamp.run/useMoney?username=&userID={userID}&conis=-{len(valid_codes)}&session=dfdfrgg",
  774. headers={}, data={})
  775. result_message += "(已回滚积分扣除)"
  776. except:
  777. result_message += "(积分回滚失败,请联系管理员)"
  778. conn.close()
  779. return jsonify({
  780. 'success': True if len(successful_codes) > 0 else False,
  781. 'message': result_message,
  782. 'success_count': len(successful_codes),
  783. 'failed_count': len(failed_codes),
  784. 'failed_codes': failed_codes,
  785. 'data': success_records
  786. })
  787. except Exception as e:
  788. # 回滚事务
  789. conn.rollback()
  790. conn.close()
  791. # 尝试回滚积分扣除
  792. try:
  793. rollback_response = requests.request("GET",
  794. f"https://user.lamp.run/useMoney?username=&userID={userID}&conis=-{len(valid_codes)}&session=dfdfrgg",
  795. headers={}, data={})
  796. except:
  797. pass
  798. return jsonify({
  799. 'success': False,
  800. 'message': f'批量处理失败: {str(e)}',
  801. 'data': None
  802. })
  803. if __name__ == '__main__':
  804. app.run(debug=True, host='0.0.0.0', port=8087)