Compare commits

..

1 Commits

Author SHA1 Message Date
roger_home_pc c5347b01a9 添加 备注 3 years ago
  1. 9
      .gitignore
  2. 0
      ai/__init__.py
  3. 3
      ai/admin.py
  4. 6
      ai/apps.py
  5. 51
      ai/migrations/0001_initial.py
  6. 23
      ai/migrations/0002_aishow_take_times_aishow_take_tokens.py
  7. 28
      ai/migrations/0003_prompttemplate.py
  8. 27
      ai/migrations/0004_cinemahall.py
  9. 18
      ai/migrations/0005_alter_aishow_created_at.py
  10. 23
      ai/migrations/0006_aishow_updated_at_alter_aishow_created_at.py
  11. 18
      ai/migrations/0007_aishow_prompt_version.py
  12. 23
      ai/migrations/0008_aishow_temp_date_aishow_template.py
  13. 18
      ai/migrations/0009_cinemahall_hall_type.py
  14. 18
      ai/migrations/0010_aishow_target.py
  15. 33
      ai/migrations/0011_aimodel_aishow_ai_model.py
  16. 18
      ai/migrations/0012_aimodel_delete_flag.py
  17. 18
      ai/migrations/0013_aimodel_current_used.py
  18. 26
      ai/migrations/0014_airuntime.py
  19. 35
      ai/migrations/0015_moviehotinfo.py
  20. 83
      ai/migrations/0016_remove_moviehotinfo_day_1_remove_moviehotinfo_day_2_and_more.py
  21. 58
      ai/migrations/0017_remove_moviehotinfo_day_1_date_and_more.py
  22. 38
      ai/migrations/0018_moviehotinfo_day1_val_moviehotinfo_day2_val_and_more.py
  23. 28
      ai/migrations/0019_moviehotinfo_title_alter_moviehotinfo_hots_and_more.py
  24. 18
      ai/migrations/0020_moviehotinfo_show_type.py
  25. 28
      ai/migrations/0021_newmoviesuggestion.py
  26. 38
      ai/migrations/0022_newmoviesuggestion_cinema_newmoviesuggestion_zz_code_and_more.py
  27. 31
      ai/migrations/0023_movieguidance.py
  28. 18
      ai/migrations/0024_aishow_is_manual_test.py
  29. 18
      ai/migrations/0025_movieguidance_type.py
  30. 18
      ai/migrations/0026_aishow_create_datetime.py
  31. 0
      ai/migrations/__init__.py
  32. 196
      ai/models.py
  33. 56
      ai/serializers.py
  34. 18
      ai/tasks.py
  35. 3
      ai/tests.py
  36. 31
      ai/urls.py
  37. 0
      ai/utils/__init__.py
  38. 235
      ai/utils/basic_func.py
  39. 50
      ai/utils/datetime_format.py
  40. 131
      ai/utils/manual_utils.py
  41. 95
      ai/utils/movie_data.py
  42. 307
      ai/utils/show_database.py
  43. 218
      ai/utils/show_func.py
  44. 185
      ai/utils/show_process.py
  45. 274
      ai/utils/show_prompt.py
  46. 324
      ai/utils/sql.py
  47. 223
      ai/views.py
  48. 5
      command.txt
  49. 0
      config/__init__.py
  50. 3
      config/admin.py
  51. 6
      config/apps.py
  52. 0
      config/migrations/__init__.py
  53. 3
      config/models.py
  54. 3
      config/tests.py
  55. 24
      config/urls.py
  56. 94
      config/views.py
  57. 6
      dingxin_toolbox_drf/__init__.py
  58. 11
      dingxin_toolbox_drf/asgi.py
  59. 27
      dingxin_toolbox_drf/celery.py
  60. 23
      dingxin_toolbox_drf/http.py
  61. 13
      dingxin_toolbox_drf/routing.py
  62. 209
      dingxin_toolbox_drf/settings.py
  63. 19
      dingxin_toolbox_drf/urls.py
  64. 0
      dspt_api/__init__.py
  65. 3
      dspt_api/admin.py
  66. 6
      dspt_api/apps.py
  67. 120
      dspt_api/migrations/0001_initial.py
  68. 18
      dspt_api/migrations/0002_ecenv_type.py
  69. 18
      dspt_api/migrations/0003_ecchannel_type.py
  70. 27
      dspt_api/migrations/0004_remove_ecapi_m_path_ecapi_type_alter_ecapi_path.py
  71. 18
      dspt_api/migrations/0005_alter_ecapiparams_value.py
  72. 22
      dspt_api/migrations/0006_rename_cinemaids_eccinemaids_ecapigroup_type.py
  73. 22
      dspt_api/migrations/0007_remove_ecapigroup_order_alter_ecapigroup_api_id.py
  74. 18
      dspt_api/migrations/0008_rename_desc_ecapi_comment.py
  75. 18
      dspt_api/migrations/0009_rename_comment_ecapi_description.py
  76. 18
      dspt_api/migrations/0010_rename_desc_ecapiparams_description.py
  77. 23
      dspt_api/migrations/0011_alter_ecrequestlog_request_and_more.py
  78. 18
      dspt_api/migrations/0012_alter_ecapi_description.py
  79. 18
      dspt_api/migrations/0013_alter_ecapiparams_description.py
  80. 18
      dspt_api/migrations/0014_ecapi_order.py
  81. 0
      dspt_api/migrations/__init__.py
  82. 117
      dspt_api/models.py
  83. 45
      dspt_api/serializers.py
  84. 3
      dspt_api/tests.py
  85. 20
      dspt_api/urls.py
  86. 0
      dspt_api/util/__init__.py
  87. 0
      dspt_api/util/api/__init__.py
  88. 41
      dspt_api/util/api/cinema_goods_pic.py
  89. 33
      dspt_api/util/api/cinema_hall_seats.py
  90. 29
      dspt_api/util/api/cinema_plays_increment.py
  91. 53
      dspt_api/util/api/ecard_detail.py
  92. 62
      dspt_api/util/api/ecard_order_detail.py
  93. 30
      dspt_api/util/api/ecard_refund.py
  94. 45
      dspt_api/util/api/ecard_regist.py
  95. 83
      dspt_api/util/api/ecard_renew.py
  96. 29
      dspt_api/util/api/ecard_seat_price.py
  97. 52
      dspt_api/util/api/goods_deduct.py
  98. 66
      dspt_api/util/api/order_buy_goods.py
  99. 4
      dspt_api/util/api/order_info.py
  100. 46
      dspt_api/util/api/order_status.py
  101. Some files were not shown because too many files have changed in this diff Show More

9
.gitignore vendored

@ -1,9 +1,2 @@
/venv/
.idea
/dx/
/logs/
/logs/dingxin.log
*.log
/celerybeat-schedule.bak
/celerybeat-schedule.dat
/celerybeat-schedule.dir
.idea

@ -1,3 +0,0 @@
from django.contrib import admin
# Register your models here.

@ -1,6 +0,0 @@
from django.apps import AppConfig
class ShowAiConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'ai'

@ -1,51 +0,0 @@
# Generated by Django 4.2.7 on 2026-06-08 07:20
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='AiShow',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('cinema', models.CharField(max_length=50)),
('zz_code', models.CharField(max_length=50)),
('show_date', models.DateField()),
('is_ai_show', models.BooleanField(default=True)),
('show', models.TextField()),
('sales', models.CharField(max_length=50)),
('prompt', models.TextField()),
('result', models.TextField()),
('message', models.TextField()),
('created_at', models.DateTimeField(auto_now_add=True)),
],
options={
'verbose_name': 'AI排片数据',
'verbose_name_plural': 'AI排片数据',
'db_table': 'ai_show_result',
},
),
migrations.CreateModel(
name='TestCinema',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('name', models.CharField(max_length=50)),
('zz_code', models.CharField(max_length=50)),
('db_config', models.TextField()),
('user_config', models.TextField()),
('is_active', models.BooleanField(default=True)),
],
options={
'verbose_name': '测试影院',
'verbose_name_plural': '测试影院',
'db_table': 'ai_show_cinema',
},
),
]

@ -1,23 +0,0 @@
# Generated by Django 4.2.7 on 2026-06-08 10:37
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='aishow',
name='take_times',
field=models.IntegerField(default=0),
),
migrations.AddField(
model_name='aishow',
name='take_tokens',
field=models.CharField(default='', max_length=2000),
),
]

@ -1,28 +0,0 @@
# Generated by Django 4.2.7 on 2026-06-09 02:00
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0002_aishow_take_times_aishow_take_tokens'),
]
operations = [
migrations.CreateModel(
name='PromptTemplate',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('prompt_type', models.CharField(max_length=50)),
('prompt_key', models.CharField(max_length=50)),
('prompt_val', models.TextField()),
('del_flag', models.BooleanField(default=False)),
],
options={
'verbose_name': '提示词',
'verbose_name_plural': '提示词',
'db_table': 'ai_prompt_template',
},
),
]

@ -1,27 +0,0 @@
# Generated by Django 4.2.7 on 2026-06-09 10:24
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0003_prompttemplate'),
]
operations = [
migrations.CreateModel(
name='CinemaHall',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('cinema_code', models.CharField(max_length=50)),
('hall_id', models.CharField(max_length=50)),
('hall_name', models.CharField(max_length=50)),
],
options={
'verbose_name': '影厅数据',
'verbose_name_plural': '影厅数据',
'db_table': 'ai_show_hall',
},
),
]

@ -1,18 +0,0 @@
# Generated by Django 4.2.7 on 2026-06-10 07:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0004_cinemahall'),
]
operations = [
migrations.AlterField(
model_name='aishow',
name='created_at',
field=models.DateTimeField(auto_now=True),
),
]

@ -1,23 +0,0 @@
# Generated by Django 4.2.7 on 2026-06-10 07:55
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0005_alter_aishow_created_at'),
]
operations = [
migrations.AddField(
model_name='aishow',
name='updated_at',
field=models.DateTimeField(auto_now=True),
),
migrations.AlterField(
model_name='aishow',
name='created_at',
field=models.DateTimeField(auto_now_add=True),
),
]

@ -1,18 +0,0 @@
# Generated by Django 4.2.7 on 2026-06-10 08:37
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0006_aishow_updated_at_alter_aishow_created_at'),
]
operations = [
migrations.AddField(
model_name='aishow',
name='prompt_version',
field=models.CharField(default='', max_length=50),
),
]

@ -1,23 +0,0 @@
# Generated by Django 4.2.7 on 2026-06-16 01:22
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0007_aishow_prompt_version'),
]
operations = [
migrations.AddField(
model_name='aishow',
name='temp_date',
field=models.CharField(default='', max_length=50),
),
migrations.AddField(
model_name='aishow',
name='template',
field=models.TextField(default=''),
),
]

@ -1,18 +0,0 @@
# Generated by Django 4.2.7 on 2026-06-17 07:12
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0008_aishow_temp_date_aishow_template'),
]
operations = [
migrations.AddField(
model_name='cinemahall',
name='hall_type',
field=models.CharField(default='', max_length=500),
),
]

@ -1,18 +0,0 @@
# Generated by Django 4.2.7 on 2026-06-29 03:11
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0009_cinemahall_hall_type'),
]
operations = [
migrations.AddField(
model_name='aishow',
name='target',
field=models.TextField(default=''),
),
]

@ -1,33 +0,0 @@
# Generated by Django 4.2.7 on 2026-07-03 14:23
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0010_aishow_target'),
]
operations = [
migrations.CreateModel(
name='AiModel',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('config_name', models.CharField(max_length=50)),
('base_url', models.CharField(max_length=100)),
('api_key', models.CharField(max_length=50)),
('model_name', models.CharField(default='', max_length=500)),
],
options={
'verbose_name': '模型配置',
'verbose_name_plural': '模型配置',
'db_table': 'ai_model_configs',
},
),
migrations.AddField(
model_name='aishow',
name='ai_model',
field=models.CharField(default='', max_length=100),
),
]

@ -1,18 +0,0 @@
# Generated by Django 4.2.7 on 2026-07-04 13:33
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0011_aimodel_aishow_ai_model'),
]
operations = [
migrations.AddField(
model_name='aimodel',
name='delete_flag',
field=models.BooleanField(default=False),
),
]

@ -1,18 +0,0 @@
# Generated by Django 4.2.7 on 2026-07-04 13:47
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0012_aimodel_delete_flag'),
]
operations = [
migrations.AddField(
model_name='aimodel',
name='current_used',
field=models.BooleanField(default=False),
),
]

@ -1,26 +0,0 @@
# Generated by Django 4.2.7 on 2026-07-04 13:58
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0013_aimodel_current_used'),
]
operations = [
migrations.CreateModel(
name='AiRuntime',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('runtime_key', models.CharField(max_length=50)),
('runtime_val', models.TextField()),
],
options={
'verbose_name': 'AI运行时',
'verbose_name_plural': 'AI运行时',
'db_table': 'ai_runtime',
},
),
]

@ -1,35 +0,0 @@
# Generated by Django 4.2.7 on 2026-07-04 15:06
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0014_airuntime'),
]
operations = [
migrations.CreateModel(
name='MovieHotInfo',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('movie_zz_code', models.CharField(max_length=50)),
('movie_name', models.CharField(max_length=50)),
('req_date', models.DateField()),
('api_response', models.TextField()),
('wants', models.CharField(max_length=50)),
('hots', models.CharField(max_length=50)),
('day_1', models.CharField(max_length=50)),
('day_2', models.CharField(max_length=50)),
('day_3', models.CharField(max_length=50)),
('day_4', models.CharField(max_length=50)),
('day_5', models.CharField(max_length=50)),
],
options={
'verbose_name': 'AI影片热度信息',
'verbose_name_plural': 'AI影片热度信息',
'db_table': 'ai_movie_hot',
},
),
]

@ -1,83 +0,0 @@
# Generated by Django 4.2.7 on 2026-07-04 15:16
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0015_moviehotinfo'),
]
operations = [
migrations.RemoveField(
model_name='moviehotinfo',
name='day_1',
),
migrations.RemoveField(
model_name='moviehotinfo',
name='day_2',
),
migrations.RemoveField(
model_name='moviehotinfo',
name='day_3',
),
migrations.RemoveField(
model_name='moviehotinfo',
name='day_4',
),
migrations.RemoveField(
model_name='moviehotinfo',
name='day_5',
),
migrations.AddField(
model_name='moviehotinfo',
name='day_1_date',
field=models.CharField(default='', max_length=50),
),
migrations.AddField(
model_name='moviehotinfo',
name='day_1_val',
field=models.CharField(default='', max_length=50),
),
migrations.AddField(
model_name='moviehotinfo',
name='day_2_date',
field=models.CharField(default='', max_length=50),
),
migrations.AddField(
model_name='moviehotinfo',
name='day_2_val',
field=models.CharField(default='', max_length=50),
),
migrations.AddField(
model_name='moviehotinfo',
name='day_3_date',
field=models.CharField(default='', max_length=50),
),
migrations.AddField(
model_name='moviehotinfo',
name='day_3_val',
field=models.CharField(default='', max_length=50),
),
migrations.AddField(
model_name='moviehotinfo',
name='day_4_date',
field=models.CharField(default='', max_length=50),
),
migrations.AddField(
model_name='moviehotinfo',
name='day_4_val',
field=models.CharField(default='', max_length=50),
),
migrations.AddField(
model_name='moviehotinfo',
name='day_5_date',
field=models.CharField(default='', max_length=50),
),
migrations.AddField(
model_name='moviehotinfo',
name='day_5_val',
field=models.CharField(default='', max_length=50),
),
]

@ -1,58 +0,0 @@
# Generated by Django 4.2.7 on 2026-07-04 15:18
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0016_remove_moviehotinfo_day_1_remove_moviehotinfo_day_2_and_more'),
]
operations = [
migrations.RemoveField(
model_name='moviehotinfo',
name='day_1_date',
),
migrations.RemoveField(
model_name='moviehotinfo',
name='day_1_val',
),
migrations.RemoveField(
model_name='moviehotinfo',
name='day_2_date',
),
migrations.RemoveField(
model_name='moviehotinfo',
name='day_2_val',
),
migrations.RemoveField(
model_name='moviehotinfo',
name='day_3_date',
),
migrations.RemoveField(
model_name='moviehotinfo',
name='day_3_val',
),
migrations.RemoveField(
model_name='moviehotinfo',
name='day_4_date',
),
migrations.RemoveField(
model_name='moviehotinfo',
name='day_4_val',
),
migrations.RemoveField(
model_name='moviehotinfo',
name='day_5_date',
),
migrations.RemoveField(
model_name='moviehotinfo',
name='day_5_val',
),
migrations.AddField(
model_name='moviehotinfo',
name='day_data',
field=models.TextField(default=''),
),
]

@ -1,38 +0,0 @@
# Generated by Django 4.2.7 on 2026-07-04 22:57
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0017_remove_moviehotinfo_day_1_date_and_more'),
]
operations = [
migrations.AddField(
model_name='moviehotinfo',
name='day1_val',
field=models.CharField(default='', max_length=50),
),
migrations.AddField(
model_name='moviehotinfo',
name='day2_val',
field=models.CharField(default='', max_length=50),
),
migrations.AddField(
model_name='moviehotinfo',
name='day3_val',
field=models.CharField(default='', max_length=50),
),
migrations.AddField(
model_name='moviehotinfo',
name='day4_val',
field=models.CharField(default='', max_length=50),
),
migrations.AddField(
model_name='moviehotinfo',
name='day5_val',
field=models.CharField(default='', max_length=50),
),
]

@ -1,28 +0,0 @@
# Generated by Django 4.2.7 on 2026-07-04 23:00
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0018_moviehotinfo_day1_val_moviehotinfo_day2_val_and_more'),
]
operations = [
migrations.AddField(
model_name='moviehotinfo',
name='title',
field=models.CharField(default='', max_length=1000),
),
migrations.AlterField(
model_name='moviehotinfo',
name='hots',
field=models.CharField(default='', max_length=50),
),
migrations.AlterField(
model_name='moviehotinfo',
name='wants',
field=models.CharField(default='', max_length=50),
),
]

@ -1,18 +0,0 @@
# Generated by Django 4.2.7 on 2026-07-05 09:37
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0019_moviehotinfo_title_alter_moviehotinfo_hots_and_more'),
]
operations = [
migrations.AddField(
model_name='moviehotinfo',
name='show_type',
field=models.CharField(default='', max_length=500),
),
]

@ -1,28 +0,0 @@
# Generated by Django 4.2.7 on 2026-07-09 10:12
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0020_moviehotinfo_show_type'),
]
operations = [
migrations.CreateModel(
name='NewMovieSuggestion',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('movie_zz_code', models.CharField(max_length=50)),
('movie_name', models.CharField(max_length=50)),
('suggestion', models.CharField(max_length=50)),
('delete_flag', models.BooleanField(default=False)),
],
options={
'verbose_name': '新片推荐排片数',
'verbose_name_plural': '新片推荐排片数',
'db_table': 'ai_new_movie_suggestion',
},
),
]

@ -1,38 +0,0 @@
# Generated by Django 4.2.7 on 2026-07-10 02:12
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0021_newmoviesuggestion'),
]
operations = [
migrations.AddField(
model_name='newmoviesuggestion',
name='cinema',
field=models.CharField(default='', max_length=50),
),
migrations.AddField(
model_name='newmoviesuggestion',
name='zz_code',
field=models.CharField(default='', max_length=50),
),
migrations.AlterField(
model_name='newmoviesuggestion',
name='movie_name',
field=models.CharField(default='', max_length=50),
),
migrations.AlterField(
model_name='newmoviesuggestion',
name='movie_zz_code',
field=models.CharField(default='', max_length=50),
),
migrations.AlterField(
model_name='newmoviesuggestion',
name='suggestion',
field=models.CharField(default='', max_length=50),
),
]

@ -1,31 +0,0 @@
# Generated by Django 4.2.7 on 2026-07-10 06:53
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0022_newmoviesuggestion_cinema_newmoviesuggestion_zz_code_and_more'),
]
operations = [
migrations.CreateModel(
name='MovieGuidance',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('cinema', models.CharField(default='', max_length=50)),
('zz_code', models.CharField(default='', max_length=50)),
('show_date', models.CharField(default='', max_length=50)),
('movie_zz_code', models.CharField(default='', max_length=50)),
('movie_name', models.CharField(default='', max_length=50)),
('guidance', models.CharField(default='', max_length=50)),
('delete_flag', models.BooleanField(default=False)),
],
options={
'verbose_name': '集团排片指导',
'verbose_name_plural': '集团排片指导',
'db_table': 'ai_movie_guidance',
},
),
]

@ -1,18 +0,0 @@
# Generated by Django 4.2.7 on 2026-07-13 02:53
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0023_movieguidance'),
]
operations = [
migrations.AddField(
model_name='aishow',
name='is_manual_test',
field=models.BooleanField(default=False),
),
]

@ -1,18 +0,0 @@
# Generated by Django 4.2.7 on 2026-07-15 02:13
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0024_aishow_is_manual_test'),
]
operations = [
migrations.AddField(
model_name='movieguidance',
name='type',
field=models.CharField(default='', max_length=50),
),
]

@ -1,18 +0,0 @@
# Generated by Django 4.2.7 on 2026-07-16 04:19
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ai', '0025_movieguidance_type'),
]
operations = [
migrations.AddField(
model_name='aishow',
name='create_datetime',
field=models.CharField(default='', max_length=50),
),
]

@ -1,196 +0,0 @@
from django.db import models
# Create your models here.
class TestCinema(models.Model):
"""
用于存储测试影院基本信息数据库配置信息
user_config用于模拟用户设置情况
is_active设置为False时不会自动生成影院的排片需要手动生成
"""
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=50)
zz_code = models.CharField(max_length=50)
db_config = models.TextField()
user_config = models.TextField()
is_active = models.BooleanField(default=True)
def __str__(self):
return self.name
class Meta:
verbose_name = '测试影院'
verbose_name_plural = '测试影院'
db_table = 'ai_show_cinema'
class PromptTemplate(models.Model):
"""
分板块的提示词模板用于动态调整提示词的内容和结构
ShowPromptVersion为当前提示词版本
"""
id = models.AutoField(primary_key=True)
prompt_type = models.CharField(max_length=50)
prompt_key = models.CharField(max_length=50)
prompt_val = models.TextField()
del_flag = models.BooleanField(default=False)
def __str__(self):
return self.prompt_key
class Meta:
verbose_name = '提示词'
verbose_name_plural = '提示词'
db_table = 'ai_prompt_template'
class AiShow(models.Model):
"""
用于存储ai生成的结果已经影院真实排片
temp_date 模板数据日期
target 目标日期已排影片数据csv格式
show 目标日期ai生成的排片数据csv格式
sales ai排片预期收入
prompt
"""
id = models.AutoField(primary_key=True)
cinema = models.CharField(max_length=50)
zz_code = models.CharField(max_length=50)
show_date = models.DateField() # 排片目标日期
is_ai_show = models.BooleanField(default=True) # 当is_ai_show为True时,记录为ai生成的排片,否则为影院真实排片
is_manual_test = models.BooleanField(default=False) # 为手动提交的提示词提供标记
ai_model = models.CharField(default='', max_length=100) # ai生成排片时使用的模型
template = models.TextField(default='') # ai生成排片时的模板日期排片数据,csv格式
temp_date = models.CharField(max_length=50, default='') # 模板数据日期
target = models.TextField(default='') # 目标日期已排影片数据,csv格式
show = models.TextField() # 目标日期ai生成的排片数据,csv格式
sales = models.CharField(max_length=50) # ai排片预期收入
prompt = models.TextField() # 生成的用户提示词部分
result = models.TextField() # ai返回结果中最终输出部分
message = models.TextField() # ai返回结果的完整信息
create_datetime = models.CharField(max_length=50, default='') # 生成的时间
created_at = models.DateTimeField(auto_now_add=True) # ai返回结果的时间
updated_at = models.DateTimeField(auto_now=True)
take_times = models.IntegerField(default=0) # 从提示词发给ai到取得返回结果的时间,单位秒
take_tokens = models.CharField(default='', max_length=2000) # ai返回结果中token消耗部分的信息
prompt_version = models.CharField(max_length=50, default='') # 使用的提示词版本
def __str__(self):
return self.cinema
class Meta:
verbose_name = 'AI排片数据'
verbose_name_plural = 'AI排片数据'
db_table = 'ai_show_result'
class CinemaHall(models.Model):
id = models.AutoField(primary_key=True)
cinema_code = models.CharField(max_length=50)
hall_id = models.CharField(max_length=50)
hall_name = models.CharField(max_length=50)
hall_type = models.CharField(max_length=500, default='')
def __str__(self):
return self.hall_name
class Meta:
verbose_name = '影厅数据'
verbose_name_plural = '影厅数据'
db_table = 'ai_show_hall'
class AiModel(models.Model):
id = models.AutoField(primary_key=True)
config_name = models.CharField(max_length=50)
base_url = models.CharField(max_length=100)
api_key = models.CharField(max_length=50)
model_name = models.CharField(max_length=500, default='')
delete_flag = models.BooleanField(default=False)
current_used = models.BooleanField(default=False)
def __str__(self):
return self.config_name
class Meta:
verbose_name = '模型配置'
verbose_name_plural = '模型配置'
db_table = 'ai_model_configs'
class AiRuntime(models.Model):
id = models.AutoField(primary_key=True)
runtime_key = models.CharField(max_length=50)
runtime_val = models.TextField()
def __str__(self):
return self.runtime_key
class Meta:
verbose_name = 'AI运行时'
verbose_name_plural = 'AI运行时'
db_table = 'ai_runtime'
class MovieHotInfo(models.Model):
id = models.AutoField(primary_key=True)
movie_zz_code = models.CharField(max_length=50)
movie_name = models.CharField(max_length=50)
req_date = models.DateField()
api_response = models.TextField()
show_type = models.CharField(max_length=500, default='')
title = models.CharField(max_length=1000, default='')
wants = models.CharField(max_length=50, default='')
hots = models.CharField(max_length=50, default='')
day1_val = models.CharField(max_length=50, default='')
day2_val = models.CharField(max_length=50, default='')
day3_val = models.CharField(max_length=50, default='')
day4_val = models.CharField(max_length=50, default='')
day5_val = models.CharField(max_length=50, default='')
day_data = models.TextField(default='')
def __str__(self):
return self.movie_name
class Meta:
verbose_name = 'AI影片热度信息'
verbose_name_plural = 'AI影片热度信息'
db_table = 'ai_movie_hot'
class NewMovieSuggestion(models.Model):
id = models.AutoField(primary_key=True)
cinema = models.CharField(max_length=50, default='')
zz_code = models.CharField(max_length=50, default='')
movie_zz_code = models.CharField(max_length=50, default='')
movie_name = models.CharField(max_length=50, default='')
suggestion = models.CharField(max_length=50, default='')
delete_flag = models.BooleanField(default=False)
def __str__(self):
return self.movie_name
class Meta:
verbose_name = '新片推荐排片数'
verbose_name_plural = '新片推荐排片数'
db_table = 'ai_new_movie_suggestion'
class MovieGuidance(models.Model):
id = models.AutoField(primary_key=True)
cinema = models.CharField(max_length=50, default='')
zz_code = models.CharField(max_length=50, default='')
show_date = models.CharField(max_length=50, default='')
movie_zz_code = models.CharField(max_length=50, default='')
movie_name = models.CharField(max_length=50, default='')
guidance = models.CharField(max_length=50, default='')
type = models.CharField(max_length=50, default='')
delete_flag = models.BooleanField(default=False)
def __str__(self):
return self.movie_name
class Meta:
verbose_name = '集团排片指导'
verbose_name_plural = '集团排片指导'
db_table = 'ai_movie_guidance'

@ -1,56 +0,0 @@
from rest_framework import serializers
from ai.models import *
class TestCinemaSerializer(serializers.ModelSerializer):
class Meta:
model = TestCinema
fields = '__all__'
class PromptTemplateSerializer(serializers.ModelSerializer):
class Meta:
model = PromptTemplate
fields = '__all__'
class AiShowSerializer(serializers.ModelSerializer):
class Meta:
model = AiShow
fields = '__all__'
class CinemaHallSerializer(serializers.ModelSerializer):
class Meta:
model = CinemaHall
fields = '__all__'
class AiModelSerializer(serializers.ModelSerializer):
class Meta:
model = AiModel
fields = '__all__'
class AiRuntimeSerializer(serializers.ModelSerializer):
class Meta:
model = AiRuntime
fields = '__all__'
class MovieHotInfoSerializer(serializers.ModelSerializer):
class Meta:
model = MovieHotInfo
fields = '__all__'
class NewMovieSuggestionSerializer(serializers.ModelSerializer):
class Meta:
model = NewMovieSuggestion
fields = '__all__'
class MovieGuidanceSerializer(serializers.ModelSerializer):
class Meta:
model = MovieGuidance
fields = '__all__'

@ -1,18 +0,0 @@
from celery import shared_task
from ai.utils.show_process import show_main_process
from ai.utils.basic_func import clear_lock_func
from ai.utils.show_func import get_new_movie
@shared_task(time_limit=18*60, soft_time_limit=18*60)
def ai_show_general():
clear_lock_func()
show_main_process()
print("task success")
return True
@shared_task(time_limit=18*60, soft_time_limit=18*60)
def get_new_movie_task():
get_new_movie()
print("task success")
return True

@ -1,3 +0,0 @@
from django.test import TestCase
# Create your tests here.

@ -1,31 +0,0 @@
"""
URL configuration for dingxin_toolbox_drf project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include
from ai.views import *
urlpatterns = [
path('manual_general_show', manual_general_show),
path('get_cinema_show_result', get_cinema_show_result),
path('clear', clear_lock),
path('report', report),
path('report_date', get_report_date_api),
path('new_movie', insert_new_movie),
path('test', manual_test),
path('test_date', get_test_date),
path('get_prompt', get_prompt),
]

@ -1,235 +0,0 @@
import datetime
import csv
import json
from ai.models import *
from io import StringIO
from django_redis import get_redis_connection
from ai.models import CinemaHall
from django.db.models import Q
# 清除redis锁
def clear_lock_func():
redis_conn = get_redis_connection()
redis_key = f'ai_show{datetime.date.today().strftime("%Y%m%d")}'
if redis_conn.exists(redis_key):
redis_conn.delete(redis_key)
print(f'清除{redis_key}成功')
# 将csv转化成字典
def csv_to_obj(csv_data):
f = StringIO(csv_data)
reader = csv.DictReader(f)
return list(reader)
# 列表转csv
def list_to_csv(rows, include_header=True):
"""
将嵌套列表转换为 CSV 字符串
:param rows: 输入数据格式为 [['col1','col2'], ['val1','val2'], ...]
:param include_header: 若为 True rows[0] 作为表头否则全部当作数据行
"""
output = StringIO()
writer = csv.writer(output, lineterminator='\r\n')
if include_header and rows:
writer.writerow(rows[0])
writer.writerows(rows[1:])
else:
writer.writerows(rows)
return output.getvalue()
# 格式化数据
def format_show_data(cinema_code: str, show_date: str, data_left: dict, data_right: dict):
# 获取影厅数据
hall = CinemaHall.objects.filter(cinema_code=cinema_code).all()
# 准备数据
data = dict()
for h in hall:
hall_dict = {'hall_name': h.hall_name, 'hall_id': h.hall_id, 'ai': [], 'real': []}
for ai in data_left:
if dict_get(ai, ['影厅id', '影厅 id']) == str(h.hall_id):
print(ai)
hall_dict['ai'].append({
'movie_name': ai['影片别名'],
'movie_id': dict_get(ai, ['本地影片id' '本地影片 id']),
'language': ai['语言'],
'show_date': ai['放映日期'],
'start': ai['开始时间'],
'end': ai['结束时间'],
'length': ai['片长'],
'duration': ai['场间']
})
for real in data_right:
if dict_get(real, ['影厅id', '影厅 id']) == str(h.hall_id):
hall_dict['real'].append({
'movie_name': real['影片别名'],
'movie_id': dict_get(real, ['本地影片id' '本地影片 id']),
'language': real['语言'],
'show_date': real['放映日期'],
'start': real['开始时间'],
'end': real['结束时间'],
'length': real['片长'],
'duration': real['场间']
})
data[h.hall_id] = hall_dict
# 格式化输出
output_list = []
output_csv = [
['影厅别名', '影片别名', '语言', '开始时间', '结束时间', '片长', '场间', '', '影厅别名', '影片别名', '语言',
'开始时间', '结束时间', '片长', '场间']]
for v in data.values():
if len(v['ai']) == 0 and len(v['real']) == 0:
output_list.append([v['hall_name'], show_date, '', '', '', '', '', '', '', '', '', '', '', '', '', ''])
output_csv.append([v['hall_name'], '', '', '', '', '', '', '', v['hall_name'], '', '', '', '', '', ''])
if len(v['ai']) >= len(v['real']):
for i in range(len(v['ai'])):
if i < len(v['real']):
a = v['ai'][i]
r = v['real'][i]
output_list.append(
[v['hall_name'], show_date, a['movie_name'], a['movie_id'], a['language'], a['start'],
a['end'], a['length'], a['duration'], r['movie_name'], r['movie_id'], r['language'],
r['start'], r['end'], r['length'], r['duration']]
)
output_csv.append(
[v['hall_name'], a['movie_name'], a['language'], a['start'], a['end'], a['length'],
a['duration'], '', v['hall_name'], r['movie_name'], r['language'], r['start'], r['end'],
r['length'], r['duration']]
)
else:
a = v['ai'][i]
output_list.append(
[v['hall_name'], show_date, a['movie_name'], a['movie_id'], a['language'], a['start'],
a['end'], a['length'], a['duration'], '', '', '', '', '', '', '']
)
output_csv.append(
[v['hall_name'], a['movie_name'], a['language'], a['start'], a['end'], a['length'],
a['duration'], '', '', '', '', '', '', '', '']
)
else:
for i in range(len(v['real'])):
if i < len(v['ai']):
a = v['ai'][i]
r = v['real'][i]
output_list.append(
[v['hall_name'], show_date, a['movie_name'], a['movie_id'], a['language'], a['start'],
a['end'], a['length'], a['duration'], r['movie_name'], r['movie_id'], r['language'],
r['start'], r['end'], r['length'], r['duration']]
)
output_csv.append(
[v['hall_name'], a['movie_name'], a['language'], a['start'], a['end'], a['length'],
a['duration'], '', v['hall_name'], r['movie_name'], r['language'], r['start'], r['end'],
r['length'], r['duration']]
)
else:
r = v['real'][i]
output_list.append(
[v['hall_name'], show_date, '', '', '', '', '', '', '', r['movie_name'], r['movie_id'],
r['language'], r['start'], r['end'], r['length'], r['duration']]
)
output_csv.append(
[v['hall_name'], '', '', '', '', '', '', '', v['hall_name'], r['movie_name'], r['language'],
r['start'], r['end'], r['length'], r['duration']]
)
return output_list, output_csv
# 获取影厅制式
def get_hall_type(cinema_code):
halls = CinemaHall.objects.filter(cinema_code=cinema_code).all()
hall_dict = dict()
for h in halls:
hall_dict[h.hall_name] = h.hall_type
return hall_dict
# 获取排片占比
def count_show(show_data):
print('count_show', show_data)
show_dict = dict()
for show in show_data:
if show['影片别名'] in show_dict.keys():
show_dict[show['影片别名']] += 1
else:
show_dict[show['影片别名']] = 1
show_dict = dict(sorted(show_dict.items(), key=lambda item: item[0], reverse=True))
show_count = []
for show, count in show_dict.items():
show_count.append(f"{show}{str(round(count / len(show_data) * 100, 2))}%,共排{str(count)}")
return '\n'.join(show_count), f"{len(show_data)}"
# 处理黑名单
def get_black_list(cinema_code: str):
black_list = json.loads(TestCinema.objects.filter(zz_code=cinema_code).first().user_config)['movie_black_list']
black_list_bool = False
black_list_str = "' '"
if len(black_list) > 0:
black_list_bool = True
black_list_str = ','.join(['%s'] * len(black_list))
return black_list_bool, black_list_str, black_list
# 获取运行时参数
def get_runtime_val(key: str):
return AiRuntime.objects.filter(runtime_key=key).first().runtime_val
# 获取当前开启的模型
def get_current_model():
return AiModel.objects.filter(Q(current_used=True) & Q(delete_flag=False)).first()
# 通不过不同key获取数据
def dict_get(_dict: dict, keys: list):
for k in keys:
if k in _dict.keys():
return _dict[k]
return False
# AI返回数据清洗
def data_cleansing(data: str):
return data.replace('', ',').replace('影厅 id', '影厅id').replace('本地影片 id', '本地影片id').replace(', ', ',')
def json_to_csv(data:list):
csv_list = ['影厅别名,影厅id,影片别名,本地影片id,语言,放映日期,开始时间,结束时间,片长,场间', ]
for d in data:
csv_list.append(
f"{d['hall_name']},{d['hall_id']},{d['movie_alias']},{d['movie_id']},{d['language']},{d['show_date']},{d['start']},{d['end']},{d['length']},{d['duration']}")
return '\n'.join(csv_list)
# 获取排片数据的起始和结束日期
def get_report_date():
start_date = datetime.datetime.strftime(
AiShow.objects.filter(is_ai_show=True).order_by('show_date').first().show_date, '%Y-%m-%d') + 'T00:00:00Z'
end_date = datetime.datetime.strftime(
AiShow.objects.filter(is_ai_show=True).order_by('-show_date').first().show_date, '%Y-%m-%d') + 'T00:00:00Z'
print(start_date, end_date)
return start_date, end_date
# 判断目标日期是否是暑期档
def is_summer(target: str, start='06-11', end='08-31') -> bool:
year = str(datetime.datetime.strptime(target, '%Y-%m-%d').year)
start_obj = datetime.datetime.strptime(f"{year}-{start}", '%Y-%m-%d').date()
end_obj = datetime.datetime.strptime(f"{year}-{end}", '%Y-%m-%d').date()
target_obj = datetime.datetime.strptime(target, '%Y-%m-%d').date()
if start_obj <= target_obj <= end_obj:
return True
return False
# 根据输入的两个日期,判端是否需要增减场次
def add_reduce_rule(template: bool, target: bool) -> str:
if template is True and target is False:
return 'decrease'
elif template is False and target is True:
return 'increase'
else:
return 'same'

@ -1,50 +0,0 @@
import datetime
from chinese_calendar import (is_holiday, is_workday)
def get_data_datetime(show_date):
show_date_obj = datetime.datetime.strptime(show_date, '%Y-%m-%d')
target_start_datetime_obj = show_date_obj + datetime.timedelta(hours=6)
target_end_datetime_obj = show_date_obj + datetime.timedelta(hours=29, minutes=59, seconds=59)
data_start_datetime_obj = show_date_obj + datetime.timedelta(days=-7) + datetime.timedelta(hours=6)
data_end_datetime_obj = show_date_obj + datetime.timedelta(hours=5, minutes=59, seconds=59)
history_start = datetime.datetime.strftime(data_start_datetime_obj, '%Y-%m-%d %H:%M:%S')
history_end = datetime.datetime.strftime(data_end_datetime_obj, '%Y-%m-%d %H:%M:%S')
target_start = datetime.datetime.strftime(target_start_datetime_obj, '%Y-%m-%d %H:%M:%S')
target_end = datetime.datetime.strftime(target_end_datetime_obj, '%Y-%m-%d %H:%M:%S')
return history_start, history_end, target_start, target_end
def get_data_datetime_template(show_date, template_date):
show_date_obj = datetime.datetime.strptime(show_date, '%Y-%m-%d')
target_start_datetime_obj = show_date_obj + datetime.timedelta(hours=6)
target_end_datetime_obj = show_date_obj + datetime.timedelta(hours=29, minutes=59, seconds=59)
template_date_obj = datetime.datetime.strptime(template_date, '%Y-%m-%d')
data_start_datetime_obj = template_date_obj + datetime.timedelta(hours=6)
data_end_datetime_obj = template_date_obj + datetime.timedelta(hours=29, minutes=59, seconds=59)
history_start = datetime.datetime.strftime(data_start_datetime_obj, '%Y-%m-%d %H:%M:%S')
history_end = datetime.datetime.strftime(data_end_datetime_obj, '%Y-%m-%d %H:%M:%S')
target_start = datetime.datetime.strftime(target_start_datetime_obj, '%Y-%m-%d %H:%M:%S')
target_end = datetime.datetime.strftime(target_end_datetime_obj, '%Y-%m-%d %H:%M:%S')
return history_start, history_end, target_start, target_end
def get_date_type(show_date, template_date):
show_date_obj = datetime.datetime.strptime(show_date, '%Y-%m-%d')
template_date_obj = datetime.datetime.strptime(template_date, '%Y-%m-%d')
result = dict()
# 处理参考数据日期
history_date_list = [(show_date_obj - datetime.timedelta(days=i)) for i in range(7, 0, -1)]
history_date = ''.join(
[f'{datetime.date.strftime(d, "%Y-%m-%d")}{"节假日" if is_holiday(d) else "工作日"}' for d in
history_date_list])
# 处理目标日期
show_date = f'{datetime.date.strftime(show_date_obj, "%Y-%m-%d")}{"节假日" if is_holiday(show_date_obj) else "工作日"}'
show_date_is_holiday = is_holiday(show_date_obj)
# 处理模板日期
template_date = f'{datetime.date.strftime(template_date_obj, "%Y-%m-%d")}{"节假日" if is_holiday(template_date_obj) else "工作日"}'
template_date_is_holiday = is_holiday(template_date_obj)
return history_date, show_date, show_date_is_holiday, template_date, template_date_is_holiday
if __name__ == '__main__':
get_date_type("2026-06-13", "2026-06-01")

@ -1,131 +0,0 @@
import csv
from io import StringIO
import pymysql
from pymysql.cursors import DictCursor
s = """
影厅别名,影厅id,影片别名,本地影片id,语言,放映日期,开始时间,结束时间,片长,场间
2 百花厅部分按摩椅,1,功夫女足,4292,国语,2026-07-14,13:00,14:46,106,0
2 百花厅部分按摩椅,1,功夫女足,4292,国语,2026-07-14,15:00,16:46,106,14
2 百花厅部分按摩椅,1,功夫女足,4292,国语,2026-07-14,17:00,18:46,106,14
2 百花厅部分按摩椅,1,功夫女足,4292,国语,2026-07-14,19:00,20:46,106,14
2 百花厅部分按摩椅,1,功夫女足,4292,国语,2026-07-14,21:00,22:46,106,14
2楼1号厅部分按摩椅,2,功夫女足,4292,国语,2026-07-14,11:00,12:46,106,0
2楼1号厅部分按摩椅,2,八仙,4296,国语,2026-07-14,13:00,15:24,144,14
2楼1号厅部分按摩椅,2,三国第一部争洛阳,4281,国语,2026-07-14,15:40,17:57,137,16
2楼1号厅部分按摩椅,2,三国第一部争洛阳,4281,国语,2026-07-14,18:10,20:27,137,13
2楼1号厅部分按摩椅,2,八仙,4296,国语,2026-07-14,20:40,23:04,144,13
2楼2号速度与激情厅部分按摩椅,3,四渡,4275,国语,2026-07-14,10:20,12:22,122,0
2楼2号速度与激情厅部分按摩椅,3,四渡,4275,国语,2026-07-14,12:35,14:37,122,13
2楼2号速度与激情厅部分按摩椅,3,四渡,4275,国语,2026-07-14,14:50,16:52,122,13
2楼2号速度与激情厅部分按摩椅,3,四渡,4275,国语,2026-07-14,17:05,19:07,122,13
2楼2号速度与激情厅部分按摩椅,3,四渡,4275,国语,2026-07-14,19:20,21:22,122,13
2楼3号厅部分按摩椅,4,功夫女足,4292,国语,2026-07-14,10:30,12:16,106,0
2楼3号厅部分按摩椅,4,小黄人与大怪兽国语,4289,国语,2026-07-14,12:30,14:00,90,14
2楼3号厅部分按摩椅,4,小黄人与大怪兽国语,4289,国语,2026-07-14,14:15,15:45,90,15
2楼3号厅部分按摩椅,4,后室,4279,原版,2026-07-14,16:00,17:51,111,15
2楼3号厅部分按摩椅,4,功夫女足,4292,国语,2026-07-14,18:05,19:51,106,14
2楼3号厅部分按摩椅,4,八仙,4296,国语,2026-07-14,20:05,22:29,144,14
2楼4号优选福励厅,5,功夫女足,4292,国语,2026-07-14,11:30,13:16,106,0
2楼4号优选福励厅,5,功夫女足,4292,国语,2026-07-14,13:30,15:16,106,14
2楼4号优选福励厅,5,功夫女足,4292,国语,2026-07-14,15:30,17:16,106,14
2楼4号优选福励厅,5,功夫女足,4292,国语,2026-07-14,17:30,19:16,106,14
2楼4号优选福励厅,5,功夫女足,4292,国语,2026-07-14,19:30,21:16,106,14
2楼4号优选福励厅,5,功夫女足,4292,国语,2026-07-14,21:30,23:16,106,14
3楼5号厅部分按摩椅,6,功夫女足,4292,国语,2026-07-14,11:05,12:51,106,0
3楼5号厅部分按摩椅,6,功夫女足,4292,国语,2026-07-14,13:05,14:51,106,14
3楼5号厅部分按摩椅,6,功夫女足,4292,国语,2026-07-14,15:05,16:51,106,14
3楼5号厅部分按摩椅,6,功夫女足,4292,国语,2026-07-14,17:05,18:51,106,14
3楼5号厅部分按摩椅,6,功夫女足,4292,国语,2026-07-14,19:05,20:51,106,14
3楼5号厅部分按摩椅,6,功夫女足,4292,国语,2026-07-14,21:05,22:51,106,14
3楼6号泰隆银行厅部分按摩椅,7,功夫女足,4292,国语,2026-07-14,12:00,13:46,106,0
3楼6号泰隆银行厅部分按摩椅,7,功夫女足,4292,国语,2026-07-14,14:00,15:46,106,14
3楼6号泰隆银行厅部分按摩椅,7,功夫女足,4292,国语,2026-07-14,16:00,17:46,106,14
3楼6号泰隆银行厅部分按摩椅,7,功夫女足,4292,国语,2026-07-14,18:00,19:46,106,14
3楼6号泰隆银行厅部分按摩椅,7,功夫女足,4292,国语,2026-07-14,20:00,21:46,106,14
3楼7号厅,8,功夫女足,4292,国语,2026-07-14,12:40,14:26,106,0
3楼7号厅,8,八仙,4296,国语,2026-07-14,14:40,17:04,144,14
3楼7号厅,8,小黄人与大怪兽国语,4289,国语,2026-07-14,17:15,18:45,90,11
3楼7号厅,8,三国第一部争洛阳,4281,国语,2026-07-14,19:00,21:17,137,15
3楼7号厅,8,后室,4279,原版,2026-07-14,21:30,23:21,111,13
2 三江VIP厅,9,功夫女足,4292,国语,2026-07-14,14:05,15:51,106,0
2 三江VIP厅,9,那山那水,4264,国语,2026-07-14,16:05,17:31,86,14
2 三江VIP厅,9,八仙,4296,国语,2026-07-14,17:45,20:09,144,14
2 三江VIP厅,9,特立独行,4280,国语,2026-07-14,20:20,22:23,123,11
"""
# 将csv转化成字典
def csv_to_obj(csv_data):
f = StringIO(csv_data)
print(csv_data, f)
reader = csv.DictReader(f)
return list(reader)
def get_real_data(cinema_code: str, show_date: str):
db_config = {
'host': '172.16.1.63',
'port': 3306,
'user': 'root',
'password': 'Cine123456',
'database': 'dingxin_toolbox',
}
db_conn = pymysql.connect(**db_config)
db_cursor = db_conn.cursor(cursor=DictCursor)
db_cursor.execute(
"SELECT * FROM dingxin_toolbox.ai_show_result WHERE zz_code=%s AND show_date=%s AND is_ai_show=%s",
(cinema_code, show_date, 0))
real_data = db_cursor.fetchone()
return real_data['show']
def count_data(data):
count = len(data) - 1
movie_dict = {}
for movie in data[1:]:
movie_name = movie[None][2]
if movie_name in movie_dict.keys():
movie_dict[movie_name] += 1
else:
movie_dict[movie_name] = 1
movie_dict = dict(sorted(movie_dict.items(), key=lambda item: item[1], reverse=True))
print(f"{count}")
for key, value in movie_dict.items():
print(f"{key}》: {value}场 占比{round(value / count * 100, 2)}%")
def _get_hall_count(show: list) -> dict:
hall_show_count = dict()
for show in show[1:]:
hall = show[None][1]
if hall in hall_show_count.keys():
hall_show_count[show[None][1]] += 1
else:
hall_show_count[show[None][1]] = 1
return hall_show_count
def get_hall_show_count(ai: list, real: list) -> dict:
ai_hall_show_count = _get_hall_count(ai)
real_hall_show_count = _get_hall_count(real)
more = ai_hall_show_count if len(ai_hall_show_count) >= len(real_hall_show_count) else real_hall_show_count
hall_show_count = dict()
for key in more.keys():
hall_show_count[key] = ai_hall_show_count[key] if ai_hall_show_count.get(key, 0) >= real_hall_show_count.get(
key, 0) else real_hall_show_count[key]
return hall_show_count
def show_data(zz_code: str, show_date: str):
real_obj = csv_to_obj(get_real_data(zz_code, show_date))
ai_obj = csv_to_obj(s)
print('ai_obj', ai_obj)
print('real_obj', real_obj)
hall_show_count = get_hall_show_count(ai_obj, real_obj)
print(hall_show_count)
if __name__ == '__main__':
count_data(csv_to_obj(s))
# show_data('33040301', '2026-07-13')

@ -1,95 +0,0 @@
from hashlib import md5
import requests
from ai.models import *
import json
from django.db.models import Q
import datetime
# 从BI的日常影片数据接口中获取信息
class MovieData:
def __init__(self):
self.salt = '53b22eda5938706a34fd9d44f097bec2'
self.ts = str(int(datetime.datetime.timestamp(datetime.datetime.now())))
self.url = 'https://nation.bi.piao51.cn/nationDataApi/restful/boxoffice/nation/movieSupportData'
# 从BI获取热度数据
def get_data_from_bi(self, movie_code, show_type):
# 基本变量定义
today_str = datetime.datetime.today().strftime('%Y-%m-%d') # 当天日期字符串
movie_name = '' # 返回的影片名称,以BI返回为准
hot_title = '' # CSV表头
hot_data = '' # 数据部分
# 如果本地有则读取本地数据
today_obj = datetime.datetime.strptime(today_str, '%Y-%m-%d')
if not MovieHotInfo.objects.filter(Q(movie_zz_code=movie_code) & Q(req_date=today_obj)).exists():
print(f'热度数据中不存在日期为{today_str}专资编码为{movie_code}数据')
params = {
'movieCode': movie_code,
'timeStamp': self.ts,
'sign': self.sign(movie_code)
}
req = requests.get(self.url, params=params)
print(req.request.url)
print(json.dumps(req.json(), indent=4))
req = req.json()
if (req['success'] is True) and req['data']['movieInfo'] != '':
print('从BI获取热度数据成功')
# 基础数据
info = req['data']['movieInfo']
movie_name = info['movie_name']
daily = req['data']['movieDailyBox']
if MovieHotInfo.objects.filter(Q(movie_name=movie_name) & Q(req_date=today_str)).exists():
print('热度数据中已包含同名影片')
return '', '', ''
# 生成标题
hot_info_list = ['影片名称', '想看数量', '鼎新热度指数']
hot_info_list.extend([f"{daily[n]['businessDate']}(销售)" for n in range(4, 6)])
hot_info_list.append(f"{daily[6]['businessDate']}(今日)")
hot_info_list.extend([f"{daily[n]['businessDate']}(预售)" for n in range(7, 9)])
hot_title = f"{','.join(hot_info_list)}"
# 生成热度指数
hot = int((self.to_number(info['xiaohongshu']) + self.to_number(info['shipinhao']) + self.to_number(
info['douyin']) + self.to_number(info['weibo'])) / 10000)
# 准备数据部分
data_list = []
for n in range(4, 6):
data_list.append({'data': f"{daily[n]['businessDate']}(销售)", 'value': f"{daily[n]['boxRate']}%"})
data_list.append({'data': f"{daily[6]['businessDate']}(今日)", 'value': f"{daily[6]['boxRate']}%"})
for n in range(7, 9):
data_list.append({'date': f"{daily[n]['businessDate']}(预售)", 'value': f"{daily[n]['boxRate']}%"})
# 写入数据
MovieHotInfo.objects.update_or_create(
movie_zz_code=movie_code,
movie_name=info['movie_name'],
req_date=today_str,
api_response=req,
show_type=show_type,
title=hot_title,
wants=info['wish_num'],
hots=hot,
day1_val=daily[4]['boxRate'],
day2_val=daily[5]['boxRate'],
day3_val=daily[6]['boxRate'],
day4_val=daily[7]['boxRate'],
day5_val=daily[8]['boxRate'],
day_data=json.dumps(data_list),
)
return movie_name, hot_title, hot_data
def sign(self, code):
_pre = md5((self.salt + f"movieCode={code}&timeStamp={self.ts}").encode()).hexdigest()
_sign = md5((_pre + self.salt).encode()).hexdigest()
return _sign
@staticmethod
def to_number(num_str):
if num_str == '--':
return 0
if '' in num_str:
return int(float(num_str.replace('', '')) * 10000)
if '亿' in num_str:
return int(float(num_str.replace('亿', '')) * 100000000)
return 0

@ -1,307 +0,0 @@
import pymysql
from chinese_calendar import is_holiday
from pymysql.cursors import DictCursor
from ai.models import *
from ai.models import TestCinema
from ai.utils.sql import *
from ai.utils.basic_func import *
import datetime
import pandas as pd
import json
class GetData:
def __init__(self, cinema):
self.conn = pymysql.connect(**json.loads(cinema.db_config))
self.cur = self.conn.cursor(cursor=DictCursor)
self.zz_code = cinema.zz_code
def exit(self):
try:
self.cur.close()
self.conn.close()
except Exception as e:
print(e)
# 获取指定日期范围的排片数据
def get_show_data(self, start_datetime, end_datetime):
# print(self.cur.mogrify(GET_SHOW_DATA, (start_datetime, end_datetime)))
self.cur.execute(GET_SHOW_DATA, (start_datetime, end_datetime))
show_data = self.cur.fetchall()
if len(show_data) == 0:
return False
show_data_mapping = {
'hall_name': '影厅别名',
'hall_id': '影厅id',
'movie_name': '影片别名',
'movie_id': '本地影片id',
'language': '语言',
'show_date': '放映日期',
'start_time': '开始时间',
'end_time': '结束时间',
'length': '片长',
'duration': '场间',
}
return self.format_to_csv(show_data, show_data_mapping)
# 获取指定日期的可放映影片
def get_available_movie(self, date):
start_datetime = datetime.datetime.strptime(date, '%Y-%m-%d') + datetime.timedelta(hours=29, minutes=59,
seconds=59)
end_datetime = datetime.datetime.strptime(date, '%Y-%m-%d') + datetime.timedelta(hours=6)
self.cur.execute(GET_AVAILABLE_MOVIE, (start_datetime, end_datetime))
available_movie = self.cur.fetchall()
available_movie_list = [
f"\t{m['cinema_movie_alias']} - 影片id:{m['cinema_movie_id']}"
for m in available_movie]
return '\n'.join(available_movie_list)
# 获取指定日期的可用于排片的影片
def get_handle_movie(self, date):
if get_runtime_val('real_target') == '0':
movie_date_start = datetime.datetime.today().replace(hour=6, minute=0, second=0, microsecond=0)
movie_date_end = datetime.datetime.strptime(date, '%Y-%m-%d') + datetime.timedelta(hours=29, minutes=59,
seconds=59)
show_date_limit = datetime.datetime.strptime(date, '%Y-%m-%d') + datetime.timedelta(hours=6, minutes=0,
seconds=0)
bl_bool, bl_str, bl_list = get_black_list(self.zz_code)
if bl_bool:
sql = GET_HANDLE_MOVIE_TEST + bl_str + ');'
print(self.cur.mogrify(sql, (movie_date_start, movie_date_end, show_date_limit, *bl_list)))
self.cur.execute(sql, (movie_date_start, movie_date_end, show_date_limit, *bl_list))
else:
sql = GET_HANDLE_MOVIE_TEST + bl_str + ');'
print(self.cur.mogrify(sql, (movie_date_start, movie_date_end, show_date_limit)))
self.cur.execute(sql, (movie_date_start, movie_date_end, show_date_limit))
else:
start_datetime = datetime.datetime.strptime(date, '%Y-%m-%d') + datetime.timedelta(hours=29, minutes=59,
seconds=59)
end_datetime = datetime.datetime.strptime(date, '%Y-%m-%d') + datetime.timedelta(hours=6)
bl_bool, bl_str, bl_list = get_black_list(self.zz_code)
if bl_bool:
sql = GET_HANDLE_MOVIE + bl_str + ');'
print(self.cur.mogrify(sql, (start_datetime, end_datetime, *bl_list)))
self.cur.execute(sql, (start_datetime, end_datetime, *bl_list))
else:
sql = GET_HANDLE_MOVIE + bl_str + ');'
print(self.cur.mogrify(sql, (start_datetime, end_datetime)))
self.cur.execute(sql, (start_datetime, end_datetime))
available_movie = self.cur.fetchall()
available_movie_list = [
f"\t{m['cinema_movie_alias']} - 影片id:{m['cinema_movie_id']},影片时长:{m['cinema_movie_time']},语言:{m['language']},制式:{m['media_type']}, 最早排片开始时间:{m['cinema_movie_start_datetime']}, 最晚排片截止时间:{m['cinema_movie_end_datetime']}"
for m in available_movie]
return '\n'.join(available_movie_list)
# 获取新上映的影片
def get_new_movie(self, date):
start_datetime = datetime.datetime.strptime(date, '%Y-%m-%d')
end_datetime = datetime.datetime.strptime(date, '%Y-%m-%d') + datetime.timedelta(hours=29, minutes=59,
seconds=59)
self.cur.execute(GET_NEW_MOVIE, (start_datetime, end_datetime))
new = self.cur.fetchall()
new_list = [f"{m['cinema_movie_alias']}" for m in new]
return new_list
# 为获取影片热度功能提供影院数据
def get_movie_info(self, date, show_type='all'):
start_datetime = datetime.datetime.strptime(date, '%Y-%m-%d') + datetime.timedelta(hours=29, minutes=59,
seconds=59)
end_datetime = datetime.datetime.strptime(date, '%Y-%m-%d') + datetime.timedelta(hours=6)
bl_bool, bl_str, bl_list = get_black_list(self.zz_code)
if bl_bool:
if show_type == "new":
sql = GET_NEW_MOVIE_INFO + bl_str + GET_MOVIE_INFO_END
self.cur.execute(sql, (start_datetime, end_datetime, *bl_list))
print(self.cur.mogrify(sql, (start_datetime, end_datetime, *bl_list)))
elif show_type == "old":
sql = GET_OLD_MOVIE_INFO + bl_str + GET_MOVIE_INFO_END
self.cur.execute(sql, (end_datetime, start_datetime, *bl_list))
print(self.cur.mogrify(sql, (start_datetime, end_datetime, *bl_list)))
else:
sql = GET_MOVIE_INFO + bl_str + GET_MOVIE_INFO_END
self.cur.execute(sql, (start_datetime, end_datetime, *bl_list))
print(self.cur.mogrify(sql, (start_datetime, end_datetime, *bl_list)))
else:
if show_type == "new":
sql = GET_NEW_MOVIE_INFO + bl_str + GET_MOVIE_INFO_END
self.cur.execute(sql, (start_datetime, end_datetime))
print(self.cur.mogrify(sql, (start_datetime, end_datetime)))
elif show_type == "old":
sql = GET_OLD_MOVIE_INFO + bl_str + GET_MOVIE_INFO_END
self.cur.execute(sql, (end_datetime, start_datetime))
print(self.cur.mogrify(sql, (start_datetime, end_datetime)))
else:
sql = GET_MOVIE_INFO + bl_str + GET_MOVIE_INFO
self.cur.execute(sql, (start_datetime, end_datetime))
print(self.cur.mogrify(sql, (start_datetime, end_datetime)))
return self.cur.fetchall()
# 按照场次获取销售数据
def get_sell_data(self, start_datetime, end_datetime):
# print(self.cur.mogrify(GET_SELL_DATA, (start_datetime, end_datetime)))
self.cur.execute(GET_SELL_DATA, (start_datetime, end_datetime, start_datetime, end_datetime))
sell_data = self.cur.fetchall()
sell_data_mapping = {
'movie_name': '影片别名',
'movie_id': '本地影片id',
'show_date': '放映日期',
'start_time': '开始时间',
'hall_name': '影厅别名',
'hall_id': '影厅id',
'total_count': '场次观影人数',
'total_income': '场次收入',
'seat_num': '影厅座位数',
'average_price': '平均价',
'rate': '上座率(单位%',
}
return self.format_to_csv(sell_data, sell_data_mapping)
# 按照影片获取销售数据
def get_sell_data_by_movie(self, start_datetime, end_datetime):
# 获取过去7天的数据
new_start_datetime = datetime.datetime.strptime(start_datetime, '%Y-%m-%d %H:%M:%S') + datetime.timedelta(
days=-7)
start_datetime = datetime.datetime.strftime(new_start_datetime, '%Y-%m-%d %H:%M:%S')
self.cur.execute(GET_SELL_DATA_BY_MOVIE, (start_datetime, end_datetime, start_datetime, end_datetime))
sell_data = self.cur.fetchall()
print('get_sell_data_by_movie', start_datetime, end_datetime, sell_data)
sell_data_mapping = {
'movie_alias_name': '影片别名',
'movie_id': '本地影片id',
'total_count': '观影总人数',
'average_show_count': '场均人次',
'average_seat_rate': '平均上座率(单位%',
'total_income': '票房总收入',
'average_ticket_price': '平均票价',
'average_show_ticket_price': '场均收入',
'show_count': '总场次数',
'show_rate': '排片占比(单位%',
}
return self.format_to_csv(sell_data, sell_data_mapping)
# 按工作日和节假日计算销售数据
def get_sell_data_by_day_type(self, start_datetime, end_datetime):
# 获取过去7天的数据
print('get_sell_data_by_day_type_start_datetime', start_datetime)
date_list = [datetime.datetime.strptime(start_datetime, '%Y-%m-%d %H:%M:%S') + datetime.timedelta(days=n) for n
in range(-7, 0, 1)]
print('get_sell_data_by_day_type', date_list)
sell_data_dict = {
'holiday': [],
'workday': [],
}
for date in date_list:
start = datetime.datetime.strftime(date, '%Y-%m-%d %H:%M:%S')
end = datetime.datetime.strftime(date + datetime.timedelta(days=1), '%Y-%m-%d %H:%M:%S')
self.cur.execute(GET_SELL_DATA_SELF_CALCULATE, (start, end))
sell_data = self.cur.fetchall()
print('get_sell_data_by_movie', start, end, sell_data)
if is_holiday(date):
sell_data_dict['holiday'].append(sell_data)
else:
sell_data_dict['workday'].append(sell_data)
movie_sell_data = dict()
for key, val in sell_data_dict.items():
print(key, val)
for sell in val:
print(sell)
for m in sell:
print(m)
if m['movie_id'] not in movie_sell_data.keys():
movie_sell_data[m['movie_id']] = {
'movie_alias_name': m['movie_alias_name'],
'movie_id': m['movie_id'],
'viewer': {
'holiday': 0,
'workday': 0,
},
'income': {
'holiday': 0.0,
'workday': 0.0,
},
'show': {
'holiday': 0,
'workday': 0,
}
}
movie_sell_data[m['movie_id']]['viewer'][key] += int(m['total_viewers'])
movie_sell_data[m['movie_id']]['income'][key] += float(m['total_income'])
movie_sell_data[m['movie_id']]['show'][key] += int(m['total_show'])
print('get_sell_data_by_day_type', movie_sell_data)
movie_sell_data_list = []
for m in movie_sell_data.values():
movie_sell_data_list.append({
'movie_alias_name': m['movie_alias_name'],
'movie_id': m['movie_id'],
'average_viewer_workday': round(
float(0 if m['show']['workday'] == 0 else m['viewer']['workday'] / m['show']['workday']), 2),
'average_ticket_price_workday': round(
float(0 if m['viewer']['workday'] == 0 else m['income']['workday'] / m['viewer']['workday']), 2),
'average_income_workday': round(
float(0 if m['show']['workday'] == 0 else m['income']['workday'] / m['show']['workday']), 2),
'average_viewer_holiday': round(
float(0 if m['show']['holiday'] == 0 else m['viewer']['holiday'] / m['show']['holiday']), 2),
'average_ticket_price_holiday': round(
float(0 if m['viewer']['holiday'] == 0 else m['income']['holiday'] / m['viewer']['holiday']), 2),
'average_income_holiday': round(
float(0 if m['show']['holiday'] == 0 else m['income']['holiday'] / m['show']['holiday']), 2),
})
sell_data_mapping = {
'movie_alias_name': '影片别名',
'movie_id': '本地影片id',
'average_viewer_workday': '场均人次(工作日)',
'average_ticket_price_workday': '平均票价(工作日)',
'average_income_workday': '场均收入(工作日)',
'average_viewer_holiday': '场均人次(节假日)',
'average_ticket_price_holiday': '平均票价(节假日)',
'average_income_holiday': '场均收入(节假日)',
}
return self.format_to_csv(movie_sell_data_list, sell_data_mapping)
# 获取指定范围的影片销售总额
def get_total_income(self, start_datetime, end_datetime):
print(self.cur.mogrify(GET_TOTAL_INCOME, (start_datetime, end_datetime, start_datetime, end_datetime)))
self.cur.execute(GET_TOTAL_INCOME, (start_datetime, end_datetime, start_datetime, end_datetime))
return self.cur.fetchone()['total_income']
# 获取影厅支持的制式
def get_hall_media_type(self):
self.cur.execute(GET_HALL_MEDIA_TYPE)
hall_data = self.cur.fetchall()
# print(hall_data)
hall_dict = dict()
# 处理成对应的字典格式 {"影厅别名": {"hall_id":影厅id,"media_type": 影片制式列表}}
for hall in hall_data:
if hall['cinema_hall_name'] not in hall_dict.keys():
hall_dict[hall['cinema_hall_name']] = {
'hall_id': hall['cinema_hall_id'],
'media_type': [hall['media_type'], ]
}
else:
hall_dict[hall['cinema_hall_name']]['media_type'].append(hall['media_type'])
# 拼装字符串
hall_str_list = []
for hall, val in hall_dict.items():
hall_str_list.append(f"\t{hall} - 影厅id:{val['hall_id']},支持制式:{''.join(val['media_type'])}")
return '\n'.join(hall_str_list)
# 获取模板日期
def get_template_date(self, start_datetime, end_datetime):
basic_val = 4
self.cur.execute(GET_TEMPLATE_DATE, (start_datetime, end_datetime, basic_val))
template_date = self.cur.fetchall()[0]['template_date']
return template_date
# 数据转csv格式字符串
@staticmethod
def format_to_csv(dict_data, mapping):
# print(dict_data)
new_dict = [{mapping[k]: v for k, v in d.items()} for d in dict_data]
return pd.DataFrame(new_dict).to_csv(index=False)
def get_media_type(self):
self.cur.execute(GET_HALL_MEDIA_TYPE)

@ -1,218 +0,0 @@
from django.db.models import Q
import datetime
from ai.models import *
from ai.utils.show_database import GetData
from ai.utils.datetime_format import *
from ai.utils.movie_data import *
from ai.utils.basic_func import *
def get_cinema_show_result_func(_zz_code, _show_date):
cinema = TestCinema.objects.filter(zz_code=_zz_code).first()
start = datetime.datetime.strftime(datetime.datetime.strptime(_show_date, '%Y-%m-%d') + datetime.timedelta(hours=6),
'%Y-%m-%d %H:%M:%S')
end = datetime.datetime.strftime(
datetime.datetime.strptime(_show_date, '%Y-%m-%d') + datetime.timedelta(hours=29, minutes=59, seconds=59),
'%Y-%m-%d %H:%M:%S')
show = ''
income = '0'
if cinema:
print(cinema)
data = GetData(cinema)
show = data.get_show_data(start, end)
income = data.get_total_income(start, end)
print(show, income)
show_db = AiShow.objects.filter(Q(is_ai_show=False) & Q(zz_code=_zz_code) & Q(show_date=_show_date)).order_by(
'-id').first()
if show is False:
show = ('影厅别名,影厅id,影片别名,本地影片id,语言,放映日期,开始时间,结束时间,片长,场间')
income = '0'
if income is None:
income = '0'
if show_db:
print('show_db', show_db)
show_db.show = show
show_db.sales = income
show_db.save()
else:
try:
AiShow.objects.create(
cinema=cinema.name,
zz_code=cinema.zz_code,
show_date=_show_date,
is_ai_show=False,
show=show,
sales=income,
prompt='',
result='',
message='',
take_times=0,
take_tokens='0',
create_datetime=datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d %H:%M:%S'),
)
except Exception as e:
print(e)
return show, income
# 获取模板日期排片数据
def get_template_show(cinema, show_date):
history_start, history_end, target_start, target_end = get_data_datetime(show_date)
data = GetData(cinema)
temp_date_obj = data.get_template_date(history_start, history_end)
temp_date = datetime.datetime.strftime(temp_date_obj, '%Y-%m-%d')
temp_start = datetime.datetime.strftime(temp_date_obj + datetime.timedelta(hours=6), '%Y-%m-%d %H:%M:%S')
temp_end = datetime.datetime.strftime(temp_date_obj + datetime.timedelta(hours=29, minutes=59, seconds=59),
'%Y-%m-%d %H:%M:%S')
temp_show = data.get_show_data(temp_start, temp_end)
return temp_show, temp_date
# 获取模板日期排片数据, 从昨天开始找一天有排片的数据做为模板,如果没有则返回None
def get_template_show_tomorrow(cinema):
i = -1
temp_show = False
while temp_show is False or i >= -3:
tomorrow = datetime.datetime.combine(datetime.date.today() + datetime.timedelta(days=i), datetime.time())
tomorrow_start = datetime.datetime.strftime(tomorrow + datetime.timedelta(hours=6), '%Y-%m-%d %H:%M:%S')
tomorrow_end = datetime.datetime.strftime(tomorrow + datetime.timedelta(hours=29, minutes=59, seconds=59),
'%Y-%m-%d %H:%M:%S')
tomorrow_str = datetime.datetime.strftime(tomorrow, '%Y-%m-%d')
data = GetData(cinema)
temp_show = data.get_show_data(tomorrow_start, tomorrow_end)
if temp_show is not False:
return temp_show, tomorrow_str
else:
i -= 1
return temp_show, ''
# 获取目标日期排片数据
def get_target_show(cinema, show_date):
history_start, history_end, target_start, target_end = get_data_datetime(show_date)
data = GetData(cinema)
target_date_show = data.get_show_data(target_start, target_end)
if not target_date_show:
target_date_show = '影厅别名,影厅id,影片别名,本地影片id,语言,放映日期,开始时间,结束时间,片长,场间'
return target_date_show
# 从BI接口获取影片热度信息
def get_movie_hot_info_from_bi(cinema, show_date):
data = GetData(cinema)
show_type_list = ['old', 'new']
for show_type in show_type_list:
print('get_movie_hot_info_from_bi', show_type)
movie = data.get_movie_info(show_date, show_type)
movie_data = MovieData()
for m in movie:
name, title, hot = movie_data.get_data_from_bi(m['cinema_movie_num'], show_type)
print('name, title, hot', name, title, hot)
return True
# 从本地数据库中获取影片热度信息
def get_all_movie_hot_info(req_date: str = 'today', show_type: str = 'old', get_num: int = 10):
if req_date == 'today':
date_sr = datetime.datetime.today().strftime('%Y-%m-%d')
else:
date_sr = req_date
hot_order_day = get_runtime_val('hot_order_day')
hot_data = MovieHotInfo.objects.filter(Q(req_date=date_sr) & Q(show_type=show_type)).order_by(hot_order_day).all()[
:get_num]
if hot_data:
print('if hot_data')
title = f"\t{hot_data[0].title}"
data_list = [title]
else:
return []
for hot in hot_data:
print(f"\t{hot.movie_name},{hot.wants},{hot.hots},{','.join([d['value'] for d in json.loads(hot.day_data)])}")
data_list.append(
f"\t{hot.movie_name},{hot.wants},{hot.hots},{','.join([d['value'] for d in json.loads(hot.day_data)])}")
print(data_list)
return data_list
# 模拟用户设置的新片推荐数量
def get_new_suggestion(cinema, show_date):
data = GetData(cinema)
tomorrow = datetime.datetime.today() + datetime.timedelta(days=-1)
show_date_obj = datetime.datetime.strptime(show_date, '%Y-%m-%d')
delta = (show_date_obj - tomorrow).days
date_list = [datetime.datetime.strftime(tomorrow + datetime.timedelta(days=i), "%Y-%m-%d") for i in
range(0, delta + 2)]
print('get_new_suggestion-date_list', date_list)
new_movie_list = []
for date in date_list:
movie = data.get_movie_info(date, 'new')
for m in movie:
print(m['cinema_movie_cn_name'])
new_movie = NewMovieSuggestion.objects.filter(
Q(movie_name=m['cinema_movie_cn_name']) & Q(zz_code=cinema.zz_code) & Q(delete_flag=False)).first()
if new_movie is not None:
if new_movie.suggestion == '0':
text = f"\t{m['cinema_movie_cn_name']} 建议排一些场次;"
else:
text = f"\t{m['cinema_movie_cn_name']} 的不同制式版本总计建议排片占比为{new_movie.suggestion}%;"
new_movie_list.append(text)
if len(new_movie_list) > 0:
return '\n'.join(new_movie_list)
return None
def get_new_movie(start_date=None):
cinema_list = TestCinema.objects.all()
start_date_obj = datetime.datetime.today()
if start_date is not None:
try:
start_date_obj = datetime.datetime.strptime(start_date, '%Y-%m-%d')
except ValueError:
print(start_date)
return False
date_list = [datetime.datetime.strftime(start_date_obj + datetime.timedelta(days=i), '%Y-%m-%d') for i in
range(1, 8)]
new_dict = dict()
new_data = False
for cinema in cinema_list:
data = GetData(cinema)
new_dict[cinema.name] = dict()
for date_val in date_list:
new_list = data.get_movie_info(date_val, 'new')
new_dict[cinema.name][date_val] = []
for new in new_list:
print(new)
if NewMovieSuggestion.objects.filter(
Q(movie_zz_code=new['cinema_movie_num']) & Q(zz_code=cinema.zz_code)).first() is None:
NewMovieSuggestion.objects.create(
cinema=cinema.name,
zz_code=cinema.zz_code,
movie_zz_code=new['cinema_movie_num'],
movie_name=new['cinema_movie_cn_name'],
suggestion=0,
delete_flag=True)
new_dict[cinema.name][date_val].append(
{'movie_zz_code': new['cinema_movie_num'], 'movie_name': new['cinema_movie_cn_name']})
new_data = True
return None if new_data == False else new_dict
# 模拟用户设置的新片推荐数量
def get_movie_guidance(cinema, show_date):
movie_guidance = MovieGuidance.objects.filter(
Q(zz_code=cinema.zz_code) & Q(show_date=show_date) & Q(delete_flag=False)).all()
if movie_guidance:
movie_list = []
for m in movie_guidance:
if m.type == 'rate':
movie_list.append(f"\t{m.movie_name} 强制排片占比必须大于{m.guidance}%")
else:
movie_list.append(f"\t{m.movie_name} 强制排片至少{m.guidance}")
return '\n'.join(movie_list)
return '\t'
def get_test_date_from_db(cinema_code: str, show_date: str) -> list:
test_data = AiShow.objects.filter(
Q(zz_code=cinema_code) & Q(show_date=show_date) & Q(is_ai_show=True)).order_by('-create_datetime').all()
return [(test.create_datetime, test.is_manual_test) for test in test_data]

@ -1,185 +0,0 @@
import json
from ai.models import *
from ai.utils.show_prompt import *
from ai.utils.show_func import *
from ai.utils.basic_func import *
import datetime
from django_redis import get_redis_connection
from django.db.models import Q
from ai.models import TestCinema
import re
# ai排片主流程
def show_main_process(zz_code=None, day_delta=None):
# 查看状态
redis_conn = get_redis_connection()
redis_key = f'ai_show{datetime.date.today().strftime("%Y%m%d")}'
if redis_conn.exists(redis_key):
return False
# 获取影院列表
redis_conn.set(redis_key, 1, ex=60 * 60 * 20)
if not zz_code:
test_cinema_list = TestCinema.objects.filter(is_active=True).all()
else:
test_cinema_list = TestCinema.objects.filter(Q(zz_code=zz_code) & Q(is_active=True)).all()
day_delta = int(get_runtime_val('day_delta')) if day_delta is None else int(day_delta)
# 获取提示词版本
prompt_ver = PromptTemplate.objects.filter(
Q(del_flag=False) & Q(prompt_type='version') & Q(prompt_key='ShowPromptVersion')).first().prompt_val
# 开始处理提示词
# 生成目标日期
show_date = datetime.date.strftime(datetime.date.today() + datetime.timedelta(days=day_delta), '%Y-%m-%d')
# 获取当前模型
model = AiModel.objects.filter(current_used=True).first()
# 按照影院生成排片
for cinema in test_cinema_list:
print(cinema.name)
show_ai = ShowAI(cinema, show_date)
# template_show, template_date = get_template_show(cinema, show_date)
template_show, template_date = get_template_show_tomorrow(cinema)
if str(get_runtime_val('real_target')) == '1':
target_show = get_target_show(cinema, show_date)
else:
target_show = '影厅别名,影厅id,影片别名,本地影片id,语言,放映日期,开始时间,结束时间,片长,场间'
prompt = show_ai.general_prompt()
if str(get_runtime_val('test')) == '0':
start = datetime.datetime.now() # 开始计时
result, message, tokens = show_ai.get_show_result_ai()
end = datetime.datetime.now() # 结束计时
print('prompt:', prompt)
print('result:', result)
print('message:', message)
print('tokens:', tokens)
# 获取排片数据
print('result:', result)
if model.config_name in ['lmstudio_qwen3.6_35b', 'company_qwen3.5_35b']:
result_obj = json.loads(result.replace('```json', '').replace('}\n```', '}').strip())
else:
result_obj = json.loads(result.strip())
show_result = result_obj['show']
# 预测排片数据
if isinstance(show_result, list):
show = json_to_csv(show_result)
else:
show = data_cleansing(show_result.replace('```', '').replace('csv', '').strip())
# 预测销售数据
sales = str(result_obj['income']).strip()
# 处理返回结果
try:
AiShow.objects.create(
cinema=cinema.name,
zz_code=cinema.zz_code,
show_date=show_date,
is_ai_show=True,
is_manual_test=False,
ai_model=model.config_name,
template=template_show,
temp_date=template_date,
target=target_show,
show=show,
sales=sales,
prompt=prompt,
result=result,
message=message,
take_times=int((end - start).seconds),
take_tokens=tokens,
prompt_version=prompt_ver,
create_datetime = datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d %H:%M:%S'),
)
except Exception as e:
print(e)
return True
def show_manual_process(zz_code: str, show_date: str, prompt: str):
cinema = TestCinema.objects.filter(zz_code=zz_code).first()
ai = ShowAI(cinema, show_date)
# 处理模板日期的排片数据
template_show, template_date = get_template_show_tomorrow(cinema)
# 处理目标日期的排片数据
if str(get_runtime_val('real_target')) == '1':
target_show = get_target_show(cinema, show_date)
else:
target_show = '影厅别名,影厅id,影片别名,本地影片id,语言,放映日期,开始时间,结束时间,片长,场间'
# 开始请求AI
start = datetime.datetime.now() # 开始计时
result, message, tokens = ai.get_show_result_ai(prompt)
end = datetime.datetime.now() # 结束计时
# 打印返回结果
print('prompt:', prompt)
print('result:', result)
print('message:', message)
print('tokens:', tokens)
# 获取当前模型根据模型处理返回结果
model = AiModel.objects.filter(current_used=True).first()
if model.config_name in ['lmstudio_qwen3.6_35b', 'company_qwen3.5_35b']:
result_obj = json.loads(result.replace('```json', '').replace('}\n```', '}').strip())
else:
result_obj = json.loads(result.strip())
# 预测排片数据
show_result = result_obj['show']
# 预测排片数据
if isinstance(show_result, list):
show = json_to_csv(show_result)
else:
show = data_cleansing(show_result.replace('```', '').replace('csv', '').strip())
# 预测销售数据
sales = str(result_obj['income']).strip()
# 处理返回结果
try:
AiShow.objects.create(
cinema=cinema.name,
zz_code=cinema.zz_code,
show_date=show_date,
is_ai_show=True,
is_manual_test=True,
ai_model=model.config_name,
template=template_show,
temp_date=template_date,
target=target_show,
show=show,
sales=sales,
prompt=prompt,
result=result,
message=message,
take_times=int((end - start).seconds),
take_tokens=tokens,
prompt_version=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
create_datetime=datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d %H:%M:%S'),
)
except Exception as e:
print(e)
return e
return result
def get_prompt_process(zz_code=None, show_date=None):
print('zz_code:', zz_code)
print('show_date:', show_date)
if zz_code == '' or show_date == '' :
return '请检查影院编码和排片日期'
# 获取影院
cinema = TestCinema.objects.filter(Q(zz_code=zz_code) & Q(is_active=True)).first()
# 获取提示词版本
prompt_ver = PromptTemplate.objects.filter(
Q(del_flag=False) & Q(prompt_type='version') & Q(prompt_key='ShowPromptVersion')).first().prompt_val
# 开始处理提示词
# 按照影院生成排片
print(cinema.name)
show_ai = ShowAI(cinema, show_date)
prompt = show_ai.general_prompt()
return prompt

@ -1,274 +0,0 @@
from django.db.models import Q
from ai.models import PromptTemplate
from ai.utils.show_database import GetData
from ai.utils.datetime_format import *
from ai.utils.show_func import *
from ai.utils.basic_func import *
import datetime
import random
import json
from openai import OpenAI
class ShowAI:
def __init__(self, cinema_info, show_date):
self.cinema = cinema_info
self.user_config = json.loads(cinema_info.user_config)
self.show_date = show_date
self.is_summer = is_summer(show_date)
self.prompt = ""
self.model = get_current_model()
self.ai_model_name = self.model.model_name
self.client = OpenAI(
api_key=self.model.api_key,
base_url=self.model.base_url,
)
# 生成提示词
# def general_prompt(self):
# data = GetData(self.cinema)
# # 准备各种日期时间
# history_start, history_end, target_start, target_end = get_data_datetime(self.show_date)
# temp = datetime.datetime.strftime(data.get_template_date(history_start, history_end), '%Y-%m-%d')
# history_date, target_date, target_date_is_holiday, template_date, template_date_is_holiday = get_date_type(
# self.show_date, temp)
# # print(history_start, history_end, target_start, target_end, history_date, show_date, template_date)
#
# # 开始处理提示词
# prompt_list = []
# # 处理排片数据
# pre_data = PromptTemplate.objects.filter(
# Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='PreData')).first().prompt_val # 获取提示词模板
# pre_data = pre_data.replace('{history_show}', data.get_show_data(history_start, history_end)) # 处理排片数据
# pre_data = pre_data.replace('{history_sales}', data.get_sell_data(history_start, history_end)) # 处理销售数据
# pre_data = pre_data.replace('{target_already_show}',
# '\t无' if data.get_show_data(target_start,
# target_end) is False else data.get_show_data(
# target_start, target_end)) # 处理目标日期已排场次数据
# pre_data = pre_data.replace('{reference_date}', history_date) # 处理参考日期
# pre_data = pre_data.replace('{template_date}', template_date) # 处理模板日期
# pre_data = pre_data.replace('{target_date}', target_date) # 处理目标日期
# prompt_list.append(pre_data)
#
# # 处理角色说明
# role = PromptTemplate.objects.filter(
# Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='Role')).first().prompt_val # 获取提示词模板
# role = role.replace('{template_date}', template_date)
# prompt_list.append(role)
#
# # 处理影片和影厅信息
# movie_hall = PromptTemplate.objects.filter(
# Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='MovieHall')).first().prompt_val # 获取提示词模板
# movie_hall = movie_hall.replace('{available_movie}', data.get_available_movie(self.show_date)) # 处理上映影片
# movie_hall = movie_hall.replace('{handle_movie}', data.get_handle_movie(self.show_date)) # 处理可排影片
# movie_hall = movie_hall.replace('{hall_info}', data.get_hall_media_type()) # 处理影厅信息
# free_hall = self.user_config['holiday_date_free_hall'] if target_date_is_holiday else self.user_config[
# 'holiday_date_free_hall']
# movie_hall = movie_hall.replace('{free_hall}',
# '\t无' if len(free_hall) == 0 else '\n'.join(
# f'\t{h};' for h in free_hall)) # 处理不可排片影厅
# prompt_list.append(movie_hall)
#
# # 影片热度和排片占比
# movie_hot = PromptTemplate.objects.filter(
# Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='Hot')).first().prompt_val # 获取提示词模板
# movie_hot = movie_hot.replace('{movie_hot}', '\n'.join(get_all_movie_hot_info(self.cinema, self.show_date)))
# prompt_list.append(movie_hot)
#
# # 处理具体要求
# rules = PromptTemplate.objects.filter(
# Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='Rules')).first().prompt_val # 获取提示词模板
# rules = rules.replace('{template_date}', template_date) # 处理模板日期
# # 获取新片
# # new_movie_str_list = []
# # new_movie = data.get_new_movie(self.show_date)
# # for new in new_movie:
# # new_movie_str_list.append(
# # f"\t增加{new}的场次,建议排{str(random.randint(2, 4))}场,可根据影片热度和口碑适当增加;")
# # rules = rules.replace('{new_movie}',
# # '\t无新片上映' if len(new_movie_str_list) == 0 else '\n'.join(
# # new_movie_str_list)) # 处理新片数据
# prompt_list.append(rules)
#
# # 处理基本规则
# basic = PromptTemplate.objects.filter(
# Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='Basic')).first().prompt_val # 获取提示词模板
# start = self.user_config['holiday_date_start'] if target_date_is_holiday else self.user_config[
# 'work_date_start']
# end = self.user_config['holiday_date_end'] if target_date_is_holiday else self.user_config['work_date_end']
# basic = basic.replace('{start}', start)
# basic = basic.replace('{end}', end)
# prompt_list.append(basic)
#
# # 处理增减场次规则
# add_reduce = PromptTemplate.objects.filter(
# Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='AddReduce')).first().prompt_val # 获取提示词模板
# prompt_list.append(add_reduce)
#
# # 处理黄金时段
# prime_time = PromptTemplate.objects.filter(
# Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='PrimeTime')).first().prompt_val # 获取提示词模板
# prompt_list.append(prime_time)
#
# # 处理暑期档
# summer = PromptTemplate.objects.filter(
# Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='Summer')).first().prompt_val # 获取提示词模板
# prompt_list.append(summer)
#
# # 处理输出目标
# output = PromptTemplate.objects.filter(
# Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='Output')).first().prompt_val # 获取提示词模板
# prompt_list.append(output)
#
# # 打印提示词
# self.prompt = '\n'.join(prompt_list)
# print(self.prompt)
# # 关闭数据库连接
# data.exit()
# return self.prompt
# 生成提示词(对应V1.2版本)
def general_prompt(self):
data = GetData(self.cinema)
# 准备各种日期时间
template_show, template_date = get_template_show_tomorrow(self.cinema)
history_start, history_end, target_start, target_end = get_data_datetime_template(self.show_date, template_date)
# temp = datetime.datetime.strftime(data.get_template_date(history_start, history_end), '%Y-%m-%d')
history_date, target_date, target_date_is_holiday, template_date, template_date_is_holiday = get_date_type(
self.show_date, template_date)
# print(history_start, history_end, target_start, target_end, history_date, show_date, template_date)
# 开始处理提示词
prompt_list = []
# 处理排片数据
pre_data = PromptTemplate.objects.filter(
Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='PreData')).first().prompt_val # 获取提示词模板
pre_data = pre_data.replace('{template_show}', template_show) # 处理排片数据
# pre_data = pre_data.replace('{history_sales}',
# data.get_sell_data_by_movie(history_start, history_end)) # 处理销售数据
pre_data = pre_data.replace('{history_sales}',
data.get_sell_data_by_day_type(history_start, history_end)) # 处理销售数据
get_movie_hot_info_from_bi(self.cinema, self.show_date) # 获取全部影片的热度信息
movie_data_old = get_all_movie_hot_info('today', 'old')
movie_data_new = get_all_movie_hot_info('today', 'new')
pre_data = pre_data.replace('{hot_movie_old}',
'\n'.join(movie_data_old) if len(movie_data_old) > 0 else '\t')
pre_data = pre_data.replace('{hot_movie_new}',
'\n'.join(movie_data_new) if len(movie_data_new) > 0 else '\t')
if get_runtime_val('real_target') == '1':
pre_data = pre_data.replace('{target_already_show}',
'\t' if data.get_show_data(target_start,
target_end) is False else data.get_show_data(
target_start, target_end)) # 处理目标日期已排场次数据
else:
pre_data = pre_data.replace('{target_already_show}', '') # 处理目标日期已排场次数据
# pre_data = pre_data.replace('{reference_date}', history_date) # 处理参考日期
pre_data = pre_data.replace('{template_date}', template_date) # 处理模板日期
pre_data = pre_data.replace('{target_date}', target_date) # 处理目标日期
prompt_list.append(pre_data)
# 处理角色说明
role = PromptTemplate.objects.filter(
Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='Role')).first().prompt_val # 获取提示词模板
role = role.replace('{template_date}', template_date)
prompt_list.append(role)
# 处理影片和影厅信息
movie_hall = PromptTemplate.objects.filter(
Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='MovieHall')).first().prompt_val # 获取提示词模板
# movie_hall = movie_hall.replace('{available_movie}', data.get_available_movie(self.show_date)) # 处理上映影片
movie_hall = movie_hall.replace('{handle_movie}', data.get_handle_movie(self.show_date)) # 处理可排影片
movie_hall = movie_hall.replace('{hall_info}', data.get_hall_media_type()) # 处理影厅信息
free_hall = self.user_config['holiday_date_free_hall'] if target_date_is_holiday else self.user_config[
'holiday_date_free_hall']
movie_hall = movie_hall.replace('{free_hall}',
'\t' if len(free_hall) == 0 else '\n'.join(
f'\t{h}' for h in free_hall)) # 处理不可排片影厅
prompt_list.append(movie_hall)
# 处理具体要求
rules = PromptTemplate.objects.filter(
Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='Rules')).first().prompt_val # 获取提示词模板
rules = rules.replace('{template_date}', template_date) # 处理模板日期
rules = rules.replace('{available_movie}', data.get_available_movie(self.show_date)) # 处理上映影片
new_suggestion = get_new_suggestion(self.cinema, self.show_date)
rules = rules.replace('{new_movie_suggestion}',
'\t' if new_suggestion is None else new_suggestion) # 处理新片推荐数量
prompt_list.append(rules)
# 处理基本规则
basic = PromptTemplate.objects.filter(
Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='Basic')).first().prompt_val # 获取提示词模板
start = self.user_config['holiday_date_start'] if target_date_is_holiday or self.is_summer else \
self.user_config['work_date_start']
end = self.user_config['holiday_date_end'] if target_date_is_holiday or self.is_summer else self.user_config[
'work_date_end']
basic = basic.replace('{start}', start)
basic = basic.replace('{end}', end)
prompt_list.append(basic)
# 处理集团排片指导
movie_guidance = PromptTemplate.objects.filter(
Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='Guide')).first().prompt_val # 获取提示词模板
guidance = get_movie_guidance(self.cinema, self.show_date)
movie_guidance = movie_guidance.replace('{movie_guidance}', guidance)
prompt_list.append(movie_guidance)
# 处理增减场次规则
add_reduce = PromptTemplate.objects.filter(
Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='AddReduce')).first().prompt_val # 获取提示词模板
add_reduce_obj = json.loads(add_reduce)
rule = add_reduce_rule(template_date_is_holiday, target_date_is_holiday)
add_reduce_str = f"{add_reduce_obj['title']}\n{add_reduce_obj[rule]}\n\n"
prompt_list.append(add_reduce_str)
# 处理黄金时段
prime_time = PromptTemplate.objects.filter(
Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='PrimeTime')).first().prompt_val # 获取提示词模板
prompt_list.append(prime_time)
# # 处理暑期档
# summer = PromptTemplate.objects.filter(
# Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='Summer')).first().prompt_val # 获取提示词模板
# prompt_list.append(summer)
# 处理输出目标
output = PromptTemplate.objects.filter(
Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='Output')).first().prompt_val # 获取提示词模板
prompt_list.append(output)
# 打印提示词
self.prompt = '\n'.join(prompt_list)
print('开始打印提示词\n', self.prompt)
# 关闭数据库连接
data.exit()
return self.prompt
# 请求AI
def get_show_result_ai(self, prompt=None):
# 生成提示词
# self.general_prompt()
# 与AI开始对话
print(f"{self.ai_model_name}开始对话")
ts = str(int(datetime.datetime.timestamp(datetime.datetime.now())))
user_id = f"{self.cinema.zz_code}-{ts}" if get_runtime_val('deepseek_cache') == 0 else self.cinema.zz_code
response = self.client.chat.completions.create(
model=self.ai_model_name,
messages=[
{'role': 'system',
'content': '你是中文AI助手。要求:1.所有思考过程必须使用中文。2.所有tool reasoning必须使用中文。3.所有规划必须使用中文。4.即使用户使用英文提问,也必须中文推理。5.最终输出使用中文。'},
{'role': 'user', 'content': self.prompt if prompt is None else prompt},
],
stream=False,
reasoning_effort="high",
extra_body={"thinking": {"type": "enabled"},
"user_id": user_id},
response_format={
'type': 'json_object'
}
)
res_json = response.model_dump_json()
res_obj = json.loads(res_json)
print(res_obj)
return res_obj['choices'][0]['message']['content'], res_json, response.usage.model_dump_json()

@ -1,324 +0,0 @@
# 排片数据
GET_SHOW_DATA = """
SELECT hi.cinema_hall_name as hall_name,
hi.cinema_hall_id as hall_id,
mi.cinema_movie_alias as movie_name,
mi.cinema_movie_id as movie_id,
mlt.cinema_movie_lang_type_desc as language,
DATE_FORMAT(ms.cinema_movie_show_start_time, '%%Y-%%m-%%d') as show_date,
DATE_FORMAT(ms.cinema_movie_show_start_time, '%%H:%%i') as start_time,
DATE_FORMAT(ms.cinema_movie_show_end_time, '%%H:%%i') as end_time,
CAST(TIME_TO_SEC(TIMEDIFF(ms.cinema_movie_show_end_time, ms.cinema_movie_show_start_time)) /
60 AS UNSIGNED) as length,
IFNULL(MINUTE(TIMEDIFF(ms.cinema_movie_show_start_time, (SELECT MAX(cinema_movie_show_end_time)
FROM cinema_movie_show t
WHERE t.cinema_hall_id = ms.cinema_hall_id
AND t.cinema_movie_show_start_date = ms.cinema_movie_show_start_date
AND t.cinema_del_flag = 1
AND ms.cinema_movie_show_start_time >= t.cinema_movie_show_end_time))),
0) as duration
FROM cinema_movie_show ms
LEFT JOIN cinema_hall_info hi ON ms.cinema_hall_id = hi.cinema_hall_id
LEFT JOIN cinema_movie_info mi ON ms.cinema_movie_id = mi.cinema_movie_id
LEFT JOIN cinema_movie_lang_type mlt ON mi.cinema_movie_lang_id = mlt.cinema_movie_lang_type_id
WHERE ms.cinema_del_flag = 1
AND ms.cinema_movie_show_start_time >= %s
AND ms.cinema_movie_show_start_time <= %s
ORDER BY show_date, hall_id, start_time;
"""
# 获取销售数据
GET_SELL_DATA = """
SELECT md.movie_name,
md.movie_id,
md.show_date,
md.start_time,
md.hall_name,
md.hall_id,
SUM(md.count) as total_count,
SUM(md.income) as total_income,
md.seat_num,
ROUND(IF(SUM(md.income) = 0, 0.0, SUM(md.income) / SUM(md.count)), 2) as average_price,
ROUND(SUM(md.count) / md.seat_num * 100, 2) as rate
FROM (
-- 售票
SELECT ms.cinema_movie_show_id as cinema_movie_show_id,
mi.cinema_movie_alias as movie_name,
mi.cinema_movie_id as movie_id,
DATE_FORMAT(ms.cinema_movie_show_start_time, '%%Y-%%m-%%d') as show_date,
CAST(TIME(ms.cinema_movie_show_start_time) AS CHAR) as start_time,
hi.cinema_hall_name as hall_name,
hi.cinema_hall_id as hall_id,
SUM(IF(sl.cinema_ticket_status <> 3, 1, 0)) as count,
SUM(IF(sl.cinema_ticket_status <> 3, sl.cinema_ticket_income, 0)) as income,
ms.cinema_hall_seat_num as seat_num
FROM cinema_movie_show ms
LEFT JOIN cinema_sell_log sl ON ms.cinema_movie_show_id = sl.cinema_movie_show_id
JOIN cinema_movie_info mi ON ms.cinema_movie_id = mi.cinema_movie_id
JOIN cinema_hall_info hi ON ms.cinema_hall_id = hi.cinema_hall_id
WHERE ms.cinema_movie_show_joinflg = 0
AND ms.cinema_movie_show_start_time >= %s
AND ms.cinema_movie_show_start_time <= %s
AND ms.cinema_del_flag = 1
AND NOT (ms.cinema_movie_show_sold_num = 0 AND ms.cinema_movie_show_status <> 1)
GROUP BY ms.cinema_movie_show_id, CAST(ms.cinema_movie_show_id AS CHAR)
UNION
-- 补登
SELECT ms.cinema_movie_show_id as cinema_movie_show_id,
mi.cinema_movie_alias as movie_name,
mi.cinema_movie_id as movie_id,
DATE_FORMAT(ms.cinema_movie_show_start_time, '%%Y-%%m-%%d') as show_date,
CAST(TIME(ms.cinema_movie_show_start_time) AS CHAR) as start_time,
hi.cinema_hall_name as hall_name,
hi.cinema_hall_id as hall_id,
SUM(sa.cinema_sell_add_num) as count,
SUM(sa.cinema_sell_add_total) as income,
ms.cinema_hall_seat_num as seat_num
FROM cinema_sell_add sa
LEFT JOIN cinema_movie_show ms ON sa.cinema_sell_add_showid = ms.cinema_movie_show_id
LEFT JOIN cinema_hall_info hall ON ms.cinema_hall_id = hall.cinema_hall_id
LEFT JOIN cinema_show_policy_map spm ON sa.cinema_sell_add_showid = spm.cinema_movie_show_id AND
sa.cinema_sell_add_policy = spm.cinema_show_policy_map_id
JOIN cinema_hall_info hi ON ms.cinema_hall_id = hi.cinema_hall_id
JOIN cinema_movie_info mi ON ms.cinema_movie_id = mi.cinema_movie_id
WHERE ms.cinema_movie_show_joinflg = 0
AND ms.cinema_movie_show_start_time >= %s
AND ms.cinema_movie_show_start_time <= %s
AND ms.cinema_del_flag = 1
AND NOT (ms.cinema_movie_show_sold_num = 0 AND ms.cinema_movie_show_status <> 1)
GROUP BY ms.cinema_movie_show_id, CAST(ms.cinema_movie_show_id AS CHAR)) as md
GROUP BY md.cinema_movie_show_id, CAST(md.cinema_movie_show_id AS CHAR)
ORDER BY md.show_date, md.hall_id, md.start_time;
"""
GET_SELL_DATA_BY_MOVIE = """
SELECT sd.movie_alias_name movie_alias_name,
sd.movie_id movie_id,
SUM(sd.total_count) total_count,
ROUND(IF(SUM(sd.total_count) = 0, 0.0, SUM(sd.total_count) / COUNT(sd.cinema_movie_show_id)),
2) average_show_count,
ROUND(IF(SUM(sd.total_count) = 0, 0.0, SUM(sd.total_count) / SUM(sd.total_seat)) * 100,
2) average_seat_rate,
SUM(sd.total_income) total_income,
ROUND(IF(SUM(sd.total_income) = 0, 0.0, SUM(sd.total_income) / SUM(sd.total_count)),
2) average_ticket_price,
ROUND(IF(SUM(sd.total_income) = 0, 0.0, SUM(sd.total_income) / COUNT(sd.cinema_movie_show_id)),
2) average_show_ticket_price,
COUNT(sd.cinema_movie_show_id) show_count,
ROUND(IF(COUNT(sd.cinema_movie_show_id) = 0, 0.0,
COUNT(sd.cinema_movie_show_id) / (SELECT COUNT(ms.cinema_movie_show_id)
FROM cinema_movie_show ms
WHERE ms.cinema_movie_show_joinflg = 0
AND ms.cinema_movie_show_start_time >= % s
AND ms.cinema_movie_show_start_time <= % s
AND ms.cinema_del_flag = 1
AND NOT (ms.cinema_movie_show_sold_num = 0 AND ms.cinema_movie_show_status <> 1))) *
100,
2) show_rate
FROM (SELECT CAST(ms.cinema_movie_show_id AS CHAR) cinema_movie_show_id,
mi.cinema_movie_id movie_id,
mi.cinema_movie_cn_name cinema_movie_name,
mi.cinema_movie_alias movie_alias_name,
SUM(IF(sl.cinema_ticket_status <> 3, 1, 0)) total_count,
SUM(IF(sl.cinema_ticket_status <> 3, sl.cinema_ticket_income, 0)) total_income,
ms.cinema_hall_seat_num total_seat
FROM cinema_movie_show ms
LEFT JOIN cinema_sell_log sl ON ms.cinema_movie_show_id = sl.cinema_movie_show_id
JOIN cinema_movie_info mi ON ms.cinema_movie_id = mi.cinema_movie_id
JOIN cinema_hall_info hi ON ms.cinema_hall_id = hi.cinema_hall_id
WHERE ms.cinema_movie_show_joinflg = 0
AND ms.cinema_movie_show_start_time >= % s
AND ms.cinema_movie_show_start_time <= % s
AND ms.cinema_del_flag = 1
AND NOT (ms.cinema_movie_show_sold_num = 0 AND ms.cinema_movie_show_status <> 1)
GROUP BY ms.cinema_movie_show_id, CAST(ms.cinema_movie_show_id AS CHAR)) sd
GROUP BY sd.movie_id ORDER BY average_show_ticket_price DESC;
"""
GET_SELL_DATA_SELF_CALCULATE = """
SELECT sd.movie_alias_name movie_alias_name,
sd.movie_id movie_id,
SUM(sd.total_viewers) total_viewers,
SUM(sd.total_income) total_income,
COUNT(sd.cinema_movie_show_id) total_show
FROM (SELECT CAST(ms.cinema_movie_show_id AS CHAR) cinema_movie_show_id,
mi.cinema_movie_alias movie_alias_name,
mi.cinema_movie_id movie_id,
SUM(IF(sl.cinema_ticket_status <> 3, 1, 0)) total_viewers,
SUM(IF(sl.cinema_ticket_status <> 3, sl.cinema_ticket_income, 0)) total_income
FROM cinema_movie_show ms
LEFT JOIN cinema_sell_log sl ON ms.cinema_movie_show_id = sl.cinema_movie_show_id
JOIN cinema_movie_info mi ON ms.cinema_movie_id = mi.cinema_movie_id
WHERE ms.cinema_movie_show_joinflg = 0
AND ms.cinema_movie_show_start_time >= %s
AND ms.cinema_movie_show_start_time < %s
AND ms.cinema_del_flag = 1
AND NOT (ms.cinema_movie_show_sold_num = 0 AND ms.cinema_movie_show_status <> 1)
GROUP BY ms.cinema_movie_show_id) sd
GROUP BY sd.movie_id ORDER BY sd.total_income DESC;
"""
# 获取指定日期的可放映影片
GET_AVAILABLE_MOVIE = """
SELECT cmi.cinema_movie_alias,
cmi.cinema_movie_id,
cmi.cinema_movie_time,
cmlt.cinema_movie_lang_type_desc as language,
scvm.system_const_val_desc as media_type,
cmi.cinema_movie_start_datetime,
cmi.cinema_movie_end_datetime
FROM cinema_movie_info cmi
JOIN cinema_movie_lang_type cmlt ON cmi.cinema_movie_lang_id = cmlt.cinema_movie_lang_type_id
JOIN system_const_val_map scvm ON cmi.cinema_movie_media_type = scvm.system_const_val_value
WHERE scvm.system_const_sub_module = 'new_media_type'
AND cmi.cinema_movie_start_datetime <= %s
AND cmi.cinema_movie_end_datetime > %s;
"""
# 获取指定日期的可用于排片的影片
GET_HANDLE_MOVIE = f"""
SELECT cmi.cinema_movie_alias,
cmi.cinema_movie_num,
cmi.cinema_movie_id,
cmi.cinema_movie_time,
cmlt.cinema_movie_lang_type_desc as language,
scvm.system_const_val_desc as media_type,
cmi.cinema_movie_start_datetime,
cmi.cinema_movie_end_datetime
FROM cinema_movie_info cmi
JOIN cinema_movie_lang_type cmlt ON cmi.cinema_movie_lang_id = cmlt.cinema_movie_lang_type_id
JOIN system_const_val_map scvm ON cmi.cinema_movie_media_type = scvm.system_const_val_value
WHERE scvm.system_const_sub_module = 'new_media_type'
AND cmi.cinema_movie_start_datetime <= %s
AND cmi.cinema_movie_end_datetime > %s
AND cmi.cinema_movie_num NOT IN (
"""
GET_HANDLE_MOVIE_TEST = """
SELECT cmi.cinema_movie_alias,
cmi.cinema_movie_num,
cmi.cinema_movie_id,
cmi.cinema_movie_time,
cmlt.cinema_movie_lang_type_desc as language,
scvm.system_const_val_desc as media_type,
cmi.cinema_movie_start_datetime,
cmi.cinema_movie_end_datetime
FROM cinema_movie_info cmi
JOIN cinema_movie_lang_type cmlt ON cmi.cinema_movie_lang_id = cmlt.cinema_movie_lang_type_id
JOIN system_const_val_map scvm ON cmi.cinema_movie_media_type = scvm.system_const_val_value
WHERE scvm.system_const_sub_module = 'new_media_type'
AND cmi.cinema_movie_id IN (SELECT ms.cinema_movie_id
FROM cinema_movie_show ms
WHERE ms.cinema_del_flag = 1
AND ms.cinema_movie_show_start_time >= %s
AND ms.cinema_movie_show_start_time <= %s
GROUP BY ms.cinema_movie_num)
AND cmi.cinema_movie_end_datetime > %s
AND cmi.cinema_movie_num NOT IN (
"""
# 获取新上映的影片
GET_NEW_MOVIE = """SELECT cmi.cinema_movie_alias,
cmi.cinema_movie_id,
cmi.cinema_movie_time,
cmlt.cinema_movie_lang_type_desc as language,
scvm.system_const_val_desc as media_type,
cmi.cinema_movie_start_datetime,
cmi.cinema_movie_end_datetime
FROM cinema_movie_info cmi
JOIN cinema_movie_lang_type cmlt ON cmi.cinema_movie_lang_id = cmlt.cinema_movie_lang_type_id
JOIN system_const_val_map scvm ON cmi.cinema_movie_media_type = scvm.system_const_val_value
WHERE scvm.system_const_sub_module = 'new_media_type'
AND cmi.cinema_movie_start_datetime >= %s
AND cmi.cinema_movie_start_datetime <= %s;"""
# 获取影厅支持的制式
GET_HALL_MEDIA_TYPE = """
SELECT chi.cinema_hall_name, cms.cinema_hall_id, scvm.system_const_val_desc as media_type
FROM cinema_movie_show cms
JOIN cinema_movie_info cmi ON cms.cinema_movie_id = cmi.cinema_movie_id
JOIN cinema_hall_info chi ON cms.cinema_hall_id = chi.cinema_hall_id
JOIN system_const_val_map scvm ON cmi.cinema_movie_media_type = scvm.system_const_val_value
WHERE scvm.system_const_sub_module = 'new_media_type'
AND chi.cinema_delete_flag = 0
GROUP BY chi.cinema_hall_id, media_type;
"""
# 获取模板日期
GET_TEMPLATE_DATE = """
SELECT cms.cinema_movie_show_start_date as template_date, COUNT(cinema_movie_show_id) as show_count
FROM cinema_movie_show cms
WHERE cms.cinema_del_flag = 1
AND cms.cinema_movie_show_start_time >= %s
AND cms.cinema_movie_show_start_time <= %s
GROUP BY cms.cinema_movie_show_start_date
HAVING show_count > (SELECT COUNT(chi.cinema_hall_id) FROM cinema_hall_info chi WHERE chi.cinema_delete_flag = 0) * %s
ORDER BY template_date DESC
LIMIT 1;
"""
# 获取目标日期的销售总额
GET_TOTAL_INCOME = """
SELECT SUM(md.income) as total_income
FROM (
-- 售票
SELECT SUM(IF(sl.cinema_ticket_status <> 3, sl.cinema_ticket_income, 0)) as income
FROM cinema_movie_show ms
LEFT JOIN cinema_sell_log sl ON ms.cinema_movie_show_id = sl.cinema_movie_show_id
JOIN cinema_movie_info mi ON ms.cinema_movie_id = mi.cinema_movie_id
JOIN cinema_hall_info hi ON ms.cinema_hall_id = hi.cinema_hall_id
WHERE ms.cinema_movie_show_joinflg = 0
AND ms.cinema_movie_show_start_time >= %s
AND ms.cinema_movie_show_start_time <= %s
AND ms.cinema_del_flag = 1
AND NOT (ms.cinema_movie_show_sold_num = 0 AND ms.cinema_movie_show_status <> 1)
UNION
-- 补登
SELECT SUM(sa.cinema_sell_add_total) as income
FROM cinema_sell_add sa
LEFT JOIN cinema_movie_show ms ON sa.cinema_sell_add_showid = ms.cinema_movie_show_id
LEFT JOIN cinema_hall_info hall ON ms.cinema_hall_id = hall.cinema_hall_id
LEFT JOIN cinema_show_policy_map spm ON sa.cinema_sell_add_showid = spm.cinema_movie_show_id AND
sa.cinema_sell_add_policy = spm.cinema_show_policy_map_id
JOIN cinema_hall_info hi ON ms.cinema_hall_id = hi.cinema_hall_id
JOIN cinema_movie_info mi ON ms.cinema_movie_id = mi.cinema_movie_id
WHERE ms.cinema_movie_show_joinflg = 0
AND ms.cinema_movie_show_start_time >= %s
AND ms.cinema_movie_show_start_time <= %s
AND ms.cinema_del_flag = 1
AND NOT (ms.cinema_movie_show_sold_num = 0 AND ms.cinema_movie_show_status <> 1)) md
"""
# 获取指定日期的可用于排片的影片
GET_MOVIE_INFO = """
SELECT cmi.cinema_movie_cn_name,
cmi.cinema_movie_num
FROM cinema_movie_info cmi
WHERE cmi.cinema_movie_start_datetime <= %s
AND cmi.cinema_movie_end_datetime > %s
AND cmi.cinema_movie_num NOT IN ("""
GET_MOVIE_INFO_END = """)
GROUP BY cmi.cinema_movie_num;
"""
# 获取指定日期的可用于排片的影片
GET_NEW_MOVIE_INFO = """
SELECT cmi.cinema_movie_cn_name,
cmi.cinema_movie_num
FROM cinema_movie_info cmi
WHERE cmi.cinema_movie_start_datetime <= %s
AND cmi.cinema_movie_start_datetime > %s
AND cmi.cinema_movie_num NOT IN ("""
GET_OLD_MOVIE_INFO = """
SELECT cmi.cinema_movie_cn_name,
cmi.cinema_movie_num
FROM cinema_movie_info cmi
WHERE cmi.cinema_movie_start_datetime <= %s
AND cmi.cinema_movie_end_datetime > %s
AND cmi.cinema_movie_num NOT IN ("""

@ -1,223 +0,0 @@
from anyio import sleep
from django.http import JsonResponse
from django.utils.timezone import make_aware, utc
from django.db.models import Q
from django.views.decorators.csrf import csrf_exempt
import json
from ai.models import *
import time
from ai.utils.show_process import show_main_process, show_manual_process, get_prompt_process
from ai.utils.show_func import *
from ai.utils.basic_func import *
# 手动触发ai排片
@csrf_exempt
def manual_general_show(request):
zz_code = request.GET.dict().get('cinema_code')
delta = request.GET.dict().get('delta')
result = show_main_process(zz_code, delta)
result_dict = {
'status': 'success' if result else 'fail',
'message': '生成成功' if result else '生成失败',
}
return JsonResponse(result_dict, json_dumps_params={'ensure_ascii': False})
# 更新指定日期的排片
@csrf_exempt
def get_cinema_show_result(request):
zz_code = request.GET.dict().get('cinema_code')
show_date = request.GET.dict().get('show_date')
print(zz_code, show_date)
show, income = get_cinema_show_result_func(zz_code, show_date)
result_dict = {
'status': 'success',
'message': '生成成功',
'show': show,
'income': income,
}
return JsonResponse(result_dict, json_dumps_params={'ensure_ascii': False})
# 清除redis锁
@csrf_exempt
def clear_lock(request):
clear_lock_func()
result_dict = {
'status': 'success',
'message': '完成',
}
return JsonResponse(result_dict, json_dumps_params={'ensure_ascii': False})
@csrf_exempt
def report(request):
zz_code = request.GET.dict().get('cinema_code')
show_date = request.GET.dict().get('show_date')
force = request.GET.dict().get('force')
test = request.GET.dict().get('test', None)
print('report-request_params', zz_code, show_date, force, test)
# cinema = TestCinema.objects.filter(zz_code=zz_code).first()
# 获取真实排片和销售数据
check_point = datetime.datetime.strftime(
datetime.datetime.strptime(show_date, '%Y-%m-%d') + datetime.timedelta(hours=30), '%Y-%m-%d %H:%M:%S')
last_real_data = AiShow.objects.filter(Q(is_ai_show=False) &
Q(zz_code=zz_code) &
Q(show_date=show_date) &
Q(updated_at__gt=check_point)).order_by('-id').first()
if (not last_real_data) or (force == '1'):
get_cinema_show_result_func(zz_code, show_date)
if test is None or test == '':
last_ai_data = AiShow.objects.filter(Q(is_ai_show=True) &
Q(zz_code=zz_code) &
Q(show_date=show_date)).order_by('-id').first()
else:
print('test', test)
last_ai_data = AiShow.objects.filter(Q(is_ai_show=True) &
Q(zz_code=zz_code) &
Q(show_date=show_date) &
Q(create_datetime=test)).first()
if not last_ai_data:
result_dict = {
'status': 'Failure',
'message': '没有查询到有效的智能排片数据,请调整日期和影院后再试!'}
return JsonResponse(result_dict, json_dumps_params={'ensure_ascii': False})
last_real_data = AiShow.objects.filter(Q(is_ai_show=False) &
Q(zz_code=zz_code) &
Q(show_date=show_date)).order_by('-id').first()
ai_dict = csv_to_obj(data_cleansing(last_ai_data.show))
real_dict = csv_to_obj(last_real_data.show)
temp_dict = csv_to_obj(last_ai_data.template)
target_dict = csv_to_obj(last_ai_data.target)
print(ai_dict, real_dict, temp_dict, target_dict)
output_list_ai_real, output_csv_ai_real = format_show_data(zz_code, show_date, ai_dict, real_dict)
output_list_ai_temp, output_csv_ai_temp = format_show_data(zz_code, show_date, ai_dict, temp_dict)
output_list_ai_target, output_cdv_ai_target = format_show_data(zz_code, show_date, ai_dict, target_dict)
# 获取影厅制式
hall_type = get_hall_type(cinema_code=zz_code)
# 计算排片占比
ai_count, ai_total = count_show(ai_dict)
real_count, real_total = count_show(real_dict)
target_count, target_total = count_show(target_dict)
template_count, template_total = count_show(temp_dict)
if last_ai_data.ai_model in ['lmstudio_qwen3.6_35b', 'company_qwen3.5_35b']:
think = json.loads(last_ai_data.message)['choices'][0]['message']['reasoning']
else:
think = json.loads(last_ai_data.message)['choices'][0]['message']['reasoning_content']
# 返回
result_dict = {
'status': 'success',
'message': '成功',
'data': {
'cinema_name': last_ai_data.cinema,
'zz_code': last_ai_data.zz_code,
'hall_type': hall_type,
'real_sales': last_real_data.sales,
'ai_sales': last_ai_data.sales,
'take_times': last_ai_data.take_times,
'take_tokens': json.loads(last_ai_data.take_tokens)['total_tokens'],
'csv': list_to_csv(output_csv_ai_real),
'real_obj': output_list_ai_real,
'template_obj': output_list_ai_temp,
'template_date': last_ai_data.temp_date,
'target_obj': output_list_ai_target,
'prompt': last_ai_data.prompt,
'ai_count': ai_count,
'real_count': real_count,
'target_count': target_count,
'template_count': template_count,
'ai_total': ai_total,
'real_total': real_total,
'target_total': target_total,
'template_total': template_total,
'result': last_ai_data.result,
'is_manual_test': last_ai_data.is_manual_test,
'prompt_version': last_ai_data.prompt_version,
'think': think,
'ai_model': last_ai_data.ai_model,
'create_time': last_ai_data.create_datetime
}
}
print(result_dict)
return JsonResponse(result_dict, json_dumps_params={'ensure_ascii': False})
# 获取已经生成排片的日期范围
@csrf_exempt
def get_report_date_api(request):
start, end = get_report_date()
result_dict = {
'status': 'success',
'message': '成功',
'start': start,
'end': end
}
print(result_dict)
return JsonResponse(result_dict, json_dumps_params={'ensure_ascii': False})
@csrf_exempt
def insert_new_movie(request):
start = request.GET.get('start')
result = get_new_movie(start)
if result is None:
data = 'None'
elif result is False:
data = '参数start格式错误,示例2026-07-11'
else:
data = result
result_dict = {
'status': 'success',
'message': '成功',
'data': data
}
print(result_dict)
return JsonResponse(result_dict, json_dumps_params={'ensure_ascii': False})
@csrf_exempt
def manual_test(request):
print('manual_test-reuest', json.loads(request.body))
body = json.loads(request.body)
cinema_code = body.get('cinema_code')
show_date = body.get('show_date')
prompt = body.get('prompt')
print('manual_test-request-params', cinema_code, show_date, prompt)
result = show_manual_process(cinema_code, show_date, prompt)
result_dict = {
'status': 'success',
'message': '成功',
'data': result
}
print(result_dict)
return JsonResponse(result_dict, json_dumps_params={'ensure_ascii': False})
@csrf_exempt
def get_test_date(request):
cinema_code = request.GET.get('cinema_code')
show_date = request.GET.get('show_date')
result_dict = {
'status': 'success',
'message': '成功',
'date': get_test_date_from_db(cinema_code, show_date)
}
print(result_dict)
return JsonResponse(result_dict, json_dumps_params={'ensure_ascii': False})
# 获取指定日和和影院的提示词用于手动验证
@csrf_exempt
def get_prompt(request):
cinema_code = request.GET.get('cinema_code')
show_date = request.GET.get('show_date')
result_dict = {
'status': 'success',
'message': '成功',
'data': get_prompt_process(cinema_code, show_date)
}
print(result_dict)
return JsonResponse(result_dict, json_dumps_params={'ensure_ascii': False})

@ -1,5 +0,0 @@
py .\manage.py runserver 0.0.0.0:8000
python manage.py runserver --skip-checks 0.0.0.0:8000
celery -A dingxin_toolbox_drf worker -l info -P solo # windows
celery -A dingxin_toolbox_drf worker -l info # linux
celery -A dingxin_toolbox_drf beat -l info

@ -1,3 +0,0 @@
from django.contrib import admin
# Register your models here.

@ -1,6 +0,0 @@
from django.apps import AppConfig
class ConfigConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'config'

@ -1,3 +0,0 @@
from django.db import models
# Create your models here.

@ -1,3 +0,0 @@
from django.test import TestCase
# Create your tests here.

@ -1,24 +0,0 @@
"""
URL configuration for dingxin_toolbox_drf project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include
from config.views import *
urlpatterns = [
path('zy_switch_svip', zy_switch_svip),
path('zy_clear_cache', zy_clear_cache)
]

@ -1,94 +0,0 @@
from django.http import JsonResponse
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
import pymysql
from pymysql.cursors import DictCursor
import redis
zy_db_config = {
'host': '10.10.0.116',
'port': 3306,
'user': 'zyds_select',
'password': 'select',
'db': 'suyi_cinema',
}
zy_redis_config = {
'host': '10.10.0.116',
'port': 6379,
'db': 0,
'decode_responses': True
}
@csrf_exempt
def zy_switch_svip(request):
"""
接口用于切换自营环境
http://172.16.1.168:8000/config/zy_switch_svip?svip=on
"""
# 切换自营环境
svip = request.GET.get('svip')
if svip == 'on':
result = zy_switch_svip_db('svip')
elif svip == 'off':
result = zy_switch_svip_db('normal')
else:
result = False
# 清除缓存
clear_result = False
if result:
clear_result = zy_clear_cache_redis()
result_dict = {
'status': 'success' if clear_result else 'error',
'message': ('切换环境成功,' if result else '切换环境失败,') + ('清除缓存成功' if clear_result else '清除缓存失败'),
}
return JsonResponse(result_dict, json_dumps_params={'ensure_ascii': False})
@csrf_exempt
def zy_clear_cache(request):
"""
接口用于清除自营缓存
http://172.16.1.168:8000/config/zy_clear_cache
"""
result = zy_clear_cache_redis()
result_dict = {
'status': 'success' if result else 'error',
'message': '清除缓存成功' if result else '清除缓存失败',
}
return JsonResponse(result_dict, json_dumps_params={'ensure_ascii': False})
def zy_switch_svip_db(env_type):
db_conn = pymysql.Connect(**zy_db_config)
cursor = db_conn.cursor(cursor=DictCursor)
select_sql = "SELECT value FROM suyi_cinema.group_kv_config gkc WHERE gkc.key = 'svip_switch';"
cursor.execute(select_sql)
query_result = cursor.fetchone()
# 若果当前值与要修改的值一至直接返回True
if (query_result['value'] == '1' and env_type == 'svip') or (query_result['value'] == '0' and env_type != 'svip'):
return True
# value 0-非华谊 1-华谊
sql_str = "UPDATE suyi_cinema.group_kv_config gkc SET gkc.value = %s WHERE gkc.key = 'svip_switch';"
if env_type == 'svip':
r = cursor.execute(sql_str, ('1',))
else:
r = cursor.execute(sql_str, ('0',))
db_conn.commit()
db_conn.close()
return True if r == 1 else False
def zy_clear_cache_redis():
r = redis.Redis(**zy_redis_config)
result = r.flushdb()
print('zy_clear_cache_redis', result)
return result
# Create your views here.

@ -1,6 +0,0 @@
import pymysql
from .celery import app as celery_app
pymysql.install_as_MySQLdb()
__all__ = ('celery_app',)

@ -8,16 +8,9 @@ https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/
"""
import os
import django
# from django.conf import settings
# # from django.core.asgi import get_asgi_application
# from channels.routing import ProtocolTypeRouter, URLRouter
from channels.routing import get_default_application
from .wsgi import *
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dingxin_toolbox_drf.settings')
# os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'backend.settings')
django.setup()
application = get_default_application()
application = get_asgi_application()

@ -1,27 +0,0 @@
import os
from celery import Celery
from celery.schedules import crontab
from django.conf import settings
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dingxin_toolbox_drf.settings')
# 创建 Celery实例
app = Celery('dingxin_toolbox_drf')
# 加载配置文件中的Celery配置
app.config_from_object('django.conf:settings', namespace='CELERY')
# 自动发现并添加任务
app.autodiscover_tasks()
# 强制单实例运行
app.conf.worker_prefetch_multiplier=1
app.conf.task_acks_late=True
# app.conf.beat_schedule = {
# 'update_client_task': {
# 'task': 'update.tasks.update_client',
# # 'schedule': crontab(hour='*'),
# 'schedule': 30,
# },
# }

@ -1,23 +0,0 @@
from django.utils.deprecation import MiddlewareMixin
class SetRemoteAddrFromForwardedFor(MiddlewareMixin):
"""
如果部署了代理使用此中间件获取远程客户端IP
在settings中注册该中间件
"""
def process_request(self, request):
# print('process_request')
# print("request.META")
# print(request.META)
try:
# print("request.META")
real_ip = request.META['HTTP_X_FORWARDED_FOR']
# print('real_ip', real_ip)
except KeyError as err:
print('HTTP_X_FORWARDED_FOR key error')
print(err)
else:
real_ip = real_ip.split(",")[0]
request.META['REMOTE_ADDR'] = real_ip

@ -1,13 +0,0 @@
from .wsgi import *
# from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
from .urls import websocket_urlpatterns
application = ProtocolTypeRouter(
{
'http': get_asgi_application(),
'websocket': URLRouter(websocket_urlpatterns)
}
)

@ -12,125 +12,11 @@ https://docs.djangoproject.com/en/4.2/ref/settings/
from pathlib import Path
import os
from env import ENV
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
print(BASE_DIR)
# 服务器IP
# # SERVER_IP = '172.16.1.63'
# # REDIS_IP = '172.16.1.63'
# SERVER_IP = '172.16.1.222'
# REDIS_IP = '172.16.1.222'
# # SERVER_IP = ''
CONFIG = {
'dev': {
'SERVER_IP': '172.16.1.168',
'WEB_SERVER_IP': '172.16.1.168',
'DB': {
"HOST": 'home.rogersun.cn',
"PORT": 3306,
"USER": "dingxin",
"PASSWORD": "cine123456",
"NAME": "dingxin_toolbox",
},
'DB_REMOTE': {
"HOST": '10.10.0.38',
"PORT": 3306,
"USER": "test",
"PASSWORD": "cine123456",
},
'REDIS_IP': '172.16.1.168',
'ECARD_DB': {
"HOST": '10.10.0.61',
"PORT": 3306,
"USER": "test",
"PASSWORD": "cine123456",
"NAME": "fws_dgp_card_db",
},
'AX_CLOUD_DB': {
"HOST": '172.16.1.63',
"PORT": 3306,
"USER": "root",
"PASSWORD": "Cine123456",
"NAME": "axshare",
}
},
'local': {
'SERVER_IP': '127.0.0.1',
'WEB_SERVER_IP': '127.0.0.1',
'DB': {
"HOST": 'home.rogersun.cn',
"PORT": 3306,
"USER": "dingxin",
"PASSWORD": "cine123456",
"NAME": "dingxin_toolbox",
},
# 'DB': {
# "HOST": '172.16.1.63',
# "PORT": 3306,
# "USER": "root",
# "PASSWORD": "Cine123456",
# "NAME": "dingxin_toolbox",
# },
'DB_REMOTE': {
"HOST": '10.10.0.38',
"PORT": 3306,
"USER": "test",
"PASSWORD": "cine123456",
},
'REDIS_IP': '127.0.0.1',
'ECARD_DB': {
"HOST": '10.10.0.61',
"PORT": 3306,
"USER": "test",
"PASSWORD": "cine123456",
"NAME": "fws_dgp_card_db",
},
'AX_CLOUD_DB': {
"HOST": '172.16.1.63',
"PORT": 3306,
"USER": "root",
"PASSWORD": "Cine123456",
"NAME": "axshare",
}
},
'prd': {
'SERVER_IP': '172.16.1.63',
'WEB_SERVER_IP': '172.16.1.222',
'DB': {
"HOST": '172.16.1.63',
"PORT": 3306,
"USER": "root",
"PASSWORD": "Cine123456",
"NAME": "dingxin_toolbox",
},
'DB_REMOTE': {
"HOST": '10.10.0.38',
"PORT": 3306,
"USER": "test",
"PASSWORD": "cine123456",
},
'REDIS_IP': '172.16.1.63',
'ECARD_DB': {
"HOST": '10.10.0.61',
"PORT": 3306,
"USER": "test",
"PASSWORD": "cine123456",
"NAME": "fws_dgp_card_db",
},
'AX_CLOUD_DB': {
"HOST": '172.16.1.63',
"PORT": 3306,
"USER": "root",
"PASSWORD": "Cine123456",
"NAME": "axshare",
}
}
}
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
@ -139,10 +25,8 @@ SECRET_KEY = 'django-insecure-hfujy!ih1uvio_p^cfdj^%8juf_wdb@szu$t=aaacd)^(zf@b%
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
# 增加异步和同步多线程的支持
os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"
ALLOWED_HOSTS = ['*']
ALLOWED_HOSTS = []
# Application definition
@ -152,22 +36,11 @@ INSTALLED_APPS = [
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'channels',
# 'daphne',
'django.contrib.staticfiles',
'corsheaders', # coreapi生成接口文档
'rest_framework',
'corsheaders', # coreapi生成接口文档
'rest_framework.authtoken', # Token验证应用
'django_filters',
'update',
'mock',
'dspt_api',
'product',
'config',
'group',
'ai',
'django_celery_beat', # 定时任务
'django_celery_results', # 定时任务
]
MIDDLEWARE = [
@ -176,7 +49,6 @@ MIDDLEWARE = [
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'dingxin_toolbox_drf.http.SetRemoteAddrFromForwardedFor',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
@ -202,46 +74,20 @@ TEMPLATES = [
WSGI_APPLICATION = 'dingxin_toolbox_drf.wsgi.application'
# 设置ASGI
ASGI_APPLICATION = 'dingxin_toolbox_drf.routing.application'
# Database
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
DATABASES = {
"default": {
"ENGINE": "django.db.backends.mysql",
# "HOST": "home.rogersun.cn",
"HOST": CONFIG[ENV]['DB']['HOST'],
"PORT": CONFIG[ENV]['DB']['PORT'],
"USER": CONFIG[ENV]['DB']['USER'],
"PASSWORD": CONFIG[ENV]['DB']['PASSWORD'],
"NAME": CONFIG[ENV]['DB']['NAME'],
}
}
CACHES = {
"default": {
'BACKEND': 'django_redis.cache.RedisCache',
# "BACKEND": "django.core.cache.backends.redis.RedisCache",
"LOCATION": f"redis://{CONFIG[ENV]['REDIS_IP']}:6379",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
"HOST": "home.rogersun.cn",
"PORT": 3306,
"USER": "root",
"PASSWORD": "Sxzgx1209",
"NAME": "dingxin_toolbox",
}
}
REST_FRAMEWORK_EXTENSIONS = {
'DEFAULT_CACHE_RESPONSE_TIMEOUT': 60 * 1, # 缓存时间
'DEFAULT_USE_CACHE': 'default', # 缓存存储
'DEFAULT_OBJECT_CACHE_KEY_FUNC': 'rest_framework_extensions.utils.default_object_cache_key_func',
'DEFAULT_LIST_CACHE_KEY_FUNC': 'rest_framework_extensions.utils.default_list_cache_key_func',
}
SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 使用Redis做为session缓存
SESSION_CACHE_ALIAS = 'default' # 指定本地session使用本地缓存名称是default
# Password validation
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
@ -268,16 +114,13 @@ LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
# USE_I18N = False
USE_TZ = True
# USE_TZ = False
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.2/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
# STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
STATIC_URL = 'static/'
# Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
@ -311,7 +154,7 @@ LOGGING = {
'file': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler',
'filename': os.path.join(BASE_DIR, "logs", "dingxin.log"),
'filename': os.path.join(BASE_DIR, "logs/dingxin.log"),
'maxBytes': 300 * 1024 * 1024,
'backupCount': 10,
'formatter': 'verbose'
@ -327,39 +170,9 @@ LOGGING = {
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': ('rest_framework.authentication.TokenAuthentication',), # 配置验证方式
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema', # 配置接口文档
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema' # 配置接口文档
}
# 跨域配置
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
# 默认时间格式
# DATE_FORMAT = '%Y-%m-%d' # 设置日期格式为年/月/日
# TIME_FORMAT = '%H:%M:%S' # 设置时间格式为小时:分钟
# DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S" # 设置日期时间格式为年/月/日 小时:分钟
# Channel 设置
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [(CONFIG[ENV]['REDIS_IP'], 6379)],
# "hosts": [os.environ.get('REDIS_URL', 'redis://127.0.0.1:6379/1')]
}
}
}
# Celery 定时任务
CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler'
CELERY_BROKER_URL = f"redis://{CONFIG[ENV]['REDIS_IP']}:6379/0"
CELERY_RESULT_BACKEND = "django-db"
CELERY_TIMEZONE = "Asia/Shanghai"
CELERY_ENABLE_UTC = False
CELERY_RESULT_EXTENDED = True # 启用后才会记录 task_name、date_started 等字段
CELERY_TASK_TRACK_STARTED = True # 记录任务开始时间
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TASK_RESULT_EXPIRES = 3600

@ -15,28 +15,13 @@ Including another URLconf
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include, re_path
from django.views.static import serve
from django.conf import settings
from django.urls import path, include
from rest_framework.documentation import include_docs_urls
from rest_framework.authtoken.views import obtain_auth_token
from update import consumers
urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'^static/(?P<path>.*)$', serve, {'document_root': settings.STATIC_ROOT}),
path('api-token-auth/', obtain_auth_token),
path('update/', include('update.urls')), # cinema Update 备注
path('ec/', include('dspt_api.urls')), # 电商平台接口
path('', include('mock.urls')),
path('update/', include('update.urls')), # update cinema
path('docs/', include_docs_urls(title='接口文档')),
path('prd/', include('product.urls')),
path('config/', include('config.urls')),
path('ai/', include('ai.urls')),
path('group/', include('group.urls')),
]
websocket_urlpatterns = [
path('ws/update/', consumers.UpdateConsumer.as_asgi())
]

@ -1,3 +0,0 @@
from django.contrib import admin
# Register your models here.

@ -1,6 +0,0 @@
from django.apps import AppConfig
class DsptApiConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'dspt_api'

@ -1,120 +0,0 @@
# Generated by Django 4.2.7 on 2024-05-23 07:57
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='CinemaIds',
fields=[
('id', models.IntegerField(primary_key=True, serialize=False)),
('env', models.CharField(max_length=10, verbose_name='环境')),
('cinema_id', models.IntegerField(verbose_name='影院id')),
('cinema_name', models.CharField(max_length=30, verbose_name='影院名称')),
('cid', models.CharField(max_length=10, verbose_name='影院cid')),
],
options={
'verbose_name': '影院cid',
'verbose_name_plural': '影院cid',
'db_table': 'ec_cinema_cid',
},
),
migrations.CreateModel(
name='EcApi',
fields=[
('id', models.IntegerField(primary_key=True, serialize=False)),
('desc', models.CharField(max_length=20, verbose_name='接口描述')),
('path', models.CharField(max_length=50, verbose_name='非会员接口地址')),
('m_path', models.CharField(max_length=50, verbose_name='会员接口地址')),
],
options={
'verbose_name': '接口',
'verbose_name_plural': '接口',
'db_table': 'ec_api',
},
),
migrations.CreateModel(
name='EcApiGroup',
fields=[
('id', models.IntegerField(primary_key=True, serialize=False)),
('group_id', models.CharField(max_length=20, verbose_name='接口分组id')),
('name', models.CharField(max_length=20, verbose_name='接口分组id')),
('order', models.IntegerField(verbose_name='子接口顺序')),
('api_id', models.IntegerField(verbose_name='接口id')),
],
options={
'verbose_name': '接口组',
'verbose_name_plural': '接口组',
'db_table': 'ec_api_group',
},
),
migrations.CreateModel(
name='EcApiParams',
fields=[
('id', models.IntegerField(primary_key=True, serialize=False)),
('api_id', models.IntegerField(verbose_name='接口id')),
('param', models.CharField(max_length=50, verbose_name='参数')),
('desc', models.CharField(max_length=500, verbose_name='参数描述')),
('value', models.CharField(max_length=500, verbose_name='参数值模版')),
('is_checked', models.BooleanField(default=False, verbose_name='是否默认勾选')),
('is_request', models.BooleanField(default=False, verbose_name='是否是必选项')),
],
options={
'verbose_name': '接口参数',
'verbose_name_plural': '接口参数',
'db_table': 'ec_api_params',
},
),
migrations.CreateModel(
name='EcChannel',
fields=[
('id', models.IntegerField(primary_key=True, serialize=False)),
('env', models.CharField(max_length=10, verbose_name='环境')),
('name', models.CharField(max_length=20, verbose_name='渠道名称')),
('pid', models.CharField(max_length=10, verbose_name='渠道id')),
('channel_key', models.CharField(max_length=20, verbose_name='渠道key')),
],
options={
'verbose_name': '渠道',
'verbose_name_plural': '渠道',
'db_table': 'ec_channel',
},
),
migrations.CreateModel(
name='EcEnv',
fields=[
('id', models.IntegerField(primary_key=True, serialize=False)),
('name', models.CharField(max_length=20, verbose_name='环境名称')),
('code', models.CharField(max_length=20, verbose_name='环境编码')),
('host', models.CharField(max_length=50, verbose_name='环境地址')),
],
options={
'verbose_name': '环境',
'verbose_name_plural': '环境',
'db_table': 'ec_env',
},
),
migrations.CreateModel(
name='EcRequestLog',
fields=[
('id', models.IntegerField(primary_key=True, serialize=False)),
('ip', models.CharField(max_length=20, verbose_name='请求ip')),
('env', models.CharField(max_length=10, verbose_name='环境')),
('request', models.CharField(max_length=500, verbose_name='请求链接')),
('response', models.CharField(max_length=10000, verbose_name='返回值')),
('request_datetime', models.DateTimeField(verbose_name='请求发送时间')),
],
options={
'verbose_name': '请求日志',
'verbose_name_plural': '请求日志',
'db_table': 'ec_request_log',
},
),
]

@ -1,18 +0,0 @@
# Generated by Django 4.2.7 on 2024-05-23 08:02
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dspt_api', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='ecenv',
name='type',
field=models.CharField(default='', max_length=20, verbose_name='会员非会员'),
),
]

@ -1,18 +0,0 @@
# Generated by Django 4.2.7 on 2024-05-23 08:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dspt_api', '0002_ecenv_type'),
]
operations = [
migrations.AddField(
model_name='ecchannel',
name='type',
field=models.CharField(default='', max_length=20, verbose_name='会员非会员'),
),
]

@ -1,27 +0,0 @@
# Generated by Django 4.2.7 on 2024-05-23 09:48
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dspt_api', '0003_ecchannel_type'),
]
operations = [
migrations.RemoveField(
model_name='ecapi',
name='m_path',
),
migrations.AddField(
model_name='ecapi',
name='type',
field=models.CharField(default='', max_length=20, verbose_name='会员非会员'),
),
migrations.AlterField(
model_name='ecapi',
name='path',
field=models.CharField(max_length=50, verbose_name='接口地址'),
),
]

@ -1,18 +0,0 @@
# Generated by Django 4.2.7 on 2024-05-23 10:23
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dspt_api', '0004_remove_ecapi_m_path_ecapi_type_alter_ecapi_path'),
]
operations = [
migrations.AlterField(
model_name='ecapiparams',
name='value',
field=models.CharField(blank=True, max_length=500, null=True, verbose_name='参数值模版'),
),
]

@ -1,22 +0,0 @@
# Generated by Django 4.2.7 on 2024-06-07 03:15
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dspt_api', '0005_alter_ecapiparams_value'),
]
operations = [
migrations.RenameModel(
old_name='CinemaIds',
new_name='EcCinemaIds',
),
migrations.AddField(
model_name='ecapigroup',
name='type',
field=models.CharField(default='', max_length=20, verbose_name='会员非会员'),
),
]

@ -1,22 +0,0 @@
# Generated by Django 4.2.7 on 2024-06-07 03:18
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dspt_api', '0006_rename_cinemaids_eccinemaids_ecapigroup_type'),
]
operations = [
migrations.RemoveField(
model_name='ecapigroup',
name='order',
),
migrations.AlterField(
model_name='ecapigroup',
name='api_id',
field=models.CharField(max_length=2000, verbose_name='接口id'),
),
]

@ -1,18 +0,0 @@
# Generated by Django 4.2.7 on 2024-07-19 02:23
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('dspt_api', '0007_remove_ecapigroup_order_alter_ecapigroup_api_id'),
]
operations = [
migrations.RenameField(
model_name='ecapi',
old_name='desc',
new_name='comment',
),
]

@ -1,18 +0,0 @@
# Generated by Django 4.2.7 on 2024-07-19 02:24
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('dspt_api', '0008_rename_desc_ecapi_comment'),
]
operations = [
migrations.RenameField(
model_name='ecapi',
old_name='comment',
new_name='description',
),
]

@ -1,18 +0,0 @@
# Generated by Django 4.2.7 on 2024-07-19 02:25
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('dspt_api', '0009_rename_comment_ecapi_description'),
]
operations = [
migrations.RenameField(
model_name='ecapiparams',
old_name='desc',
new_name='description',
),
]

@ -1,23 +0,0 @@
# Generated by Django 4.2.7 on 2024-07-29 05:56
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dspt_api', '0010_rename_desc_ecapiparams_description'),
]
operations = [
migrations.AlterField(
model_name='ecrequestlog',
name='request',
field=models.CharField(max_length=5000, verbose_name='请求链接'),
),
migrations.AlterField(
model_name='ecrequestlog',
name='response',
field=models.TextField(verbose_name='返回值'),
),
]

@ -1,18 +0,0 @@
# Generated by Django 4.2.7 on 2024-08-05 09:42
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dspt_api', '0011_alter_ecrequestlog_request_and_more'),
]
operations = [
migrations.AlterField(
model_name='ecapi',
name='description',
field=models.CharField(max_length=50, verbose_name='接口描述'),
),
]

@ -1,18 +0,0 @@
# Generated by Django 4.2.7 on 2024-08-05 10:22
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dspt_api', '0012_alter_ecapi_description'),
]
operations = [
migrations.AlterField(
model_name='ecapiparams',
name='description',
field=models.CharField(max_length=5000, verbose_name='参数描述'),
),
]

@ -1,18 +0,0 @@
# Generated by Django 4.2.7 on 2024-08-29 00:30
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dspt_api', '0013_alter_ecapiparams_description'),
]
operations = [
migrations.AddField(
model_name='ecapi',
name='order',
field=models.IntegerField(default=9999, verbose_name='显示顺序'),
),
]

@ -1,117 +0,0 @@
from django.db import models
class EcChannel(models.Model):
id = models.IntegerField(primary_key=True)
env = models.CharField(verbose_name='环境', max_length=10, null=False) # 电商平台 dspt 自营电商 zyds
name = models.CharField(verbose_name='渠道名称', max_length=20, null=False) # 电商平台 dspt 自营电商 zyds
pid = models.CharField(verbose_name='渠道id', max_length=10, null=False) # pid
channel_key = models.CharField(verbose_name='渠道key', max_length=20, null=False) # pid key
type = models.CharField(verbose_name='会员非会员', max_length=20, default='', null=False) # 会员 member 非会员 nonmember
def __str__(self):
return self.name
class Meta:
verbose_name = '渠道'
verbose_name_plural = '渠道'
db_table = 'ec_channel'
class EcEnv(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(verbose_name='环境名称', max_length=20, null=False) # 电商平台 自营电商
code = models.CharField(verbose_name='环境编码', max_length=20, null=False) # 电商平台 dspt 自营电商 zyds
type = models.CharField(verbose_name='会员非会员', max_length=20, default='', null=False) # 会员 member 非会员 nonmember
host = models.CharField(verbose_name='环境地址', max_length=50, null=False) # 环境地址
def __str__(self):
return self.name
class Meta:
verbose_name = '环境'
verbose_name_plural = '环境'
db_table = 'ec_env'
class EcApi(models.Model):
id = models.IntegerField(primary_key=True)
description = models.CharField(verbose_name='接口描述', max_length=50, null=False)
path = models.CharField(verbose_name='接口地址', max_length=50, null=False)
type = models.CharField(verbose_name='会员非会员', max_length=20, default='', null=False) # 会员 member 非会员 nonmember
order = models.IntegerField(verbose_name='显示顺序', default=9999)
def __str__(self):
return self.description
class Meta:
verbose_name = '接口'
verbose_name_plural = '接口'
db_table = 'ec_api'
class EcApiParams(models.Model):
id = models.IntegerField(primary_key=True)
api_id = models.IntegerField(verbose_name='接口id', null=False)
param = models.CharField(verbose_name='参数', max_length=50, null=False)
description = models.CharField(verbose_name='参数描述', max_length=5000, null=False)
value = models.CharField(verbose_name='参数值模版', max_length=500, null=True, blank=True)
is_checked = models.BooleanField(verbose_name='是否默认勾选', null=False, default=False)
is_request = models.BooleanField(verbose_name='是否是必选项', null=False, default=False)
def __str__(self):
return self.param
class Meta:
verbose_name = '接口参数'
verbose_name_plural = '接口参数'
db_table = 'ec_api_params'
class EcCinemaIds(models.Model):
id = models.IntegerField(primary_key=True)
env = models.CharField(verbose_name='环境', max_length=10, null=False) # 电商平台 dspt 自营电商 zyds
cinema_id = models.IntegerField(verbose_name='影院id', null=False)
cinema_name = models.CharField(verbose_name='影院名称', max_length=30, null=False)
cid = models.CharField(verbose_name='影院cid', max_length=10, null=False)
def __str__(self):
return self.cid
class Meta:
verbose_name = '影院cid'
verbose_name_plural = '影院cid'
db_table = 'ec_cinema_cid'
class EcRequestLog(models.Model):
id = models.IntegerField(primary_key=True)
ip = models.CharField(verbose_name='请求ip', max_length=20, null=False) # 接口测试人的ip
env = models.CharField(verbose_name='环境', max_length=10, null=False) # 电商平台 dspt 自营电商 zyds
request = models.CharField(verbose_name='请求链接', max_length=5000, null=False)
response = models.TextField(verbose_name='返回值', null=False)
request_datetime = models.DateTimeField(verbose_name='请求发送时间', null=False)
def __str__(self):
return self.ip
class Meta:
verbose_name = '请求日志'
verbose_name_plural = '请求日志'
db_table = 'ec_request_log'
class EcApiGroup(models.Model):
id = models.IntegerField(primary_key=True)
group_id = models.CharField(verbose_name='接口分组id', max_length=20, null=False)
name = models.CharField(verbose_name='接口分组id', max_length=20, null=False)
api_id = models.CharField(verbose_name='接口id', max_length=2000, null=False)
type = models.CharField(verbose_name='会员非会员', max_length=20, default='', null=False) # 会员 member 非会员 nonmember
def __str__(self):
return self.name
class Meta:
verbose_name = '接口组'
verbose_name_plural = '接口组'
db_table = 'ec_api_group'

@ -1,45 +0,0 @@
from rest_framework import serializers
from dspt_api.models import EcChannel, EcEnv, EcApi, EcApiParams, EcCinemaIds, EcRequestLog, EcApiGroup
class EcChannelSerializer(serializers.ModelSerializer):
class Meta:
model = EcChannel
fields = '__all__'
class EcEnvSerializer(serializers.ModelSerializer):
class Meta:
model = EcEnv
fields = '__all__'
class EcApiSerializer(serializers.ModelSerializer):
class Meta:
model = EcApi
fields = '__all__'
class EcApiParamsSerializer(serializers.ModelSerializer):
class Meta:
model = EcApiParams
fields = '__all__'
class EcCinemaIdsSerializer(serializers.ModelSerializer):
class Meta:
model = EcCinemaIds
fields = '__all__'
class EcRequestLogSerializer(serializers.ModelSerializer):
class Meta:
model = EcRequestLog
fields = '__all__'
class EcApiGroupSerializer(serializers.ModelSerializer):
class Meta:
model = EcApiGroup
fields = '__all__'

@ -1,3 +0,0 @@
from django.test import TestCase
# Create your tests here.

@ -1,20 +0,0 @@
from dspt_api import views
from django.urls import path
urlpatterns = [
path('get_channel', views.EcChannelViewSet.as_view({'get': 'list'}), name='get_ec_channel'),
path('get_env', views.EcEnvViewSet.as_view({'get': 'list'}), name='get_ec_env'),
path('get_api', views.EcApiViewSet.as_view({'get': 'list'}), name='get_ec_api'),
path('get_api_params', views.EcApiParamsViewSet.as_view({'get': 'list'}), name='get_ec_api_params'),
path('get_cinema_ids', views.EcCinemaIdsViewSet.as_view({'get': 'list'}), name='get_ec_cinema_ids'),
path('get_request_log', views.EcRequestLogViewSet.as_view({'get': 'list'}), name='get_ec_request_log'),
path('get_api_group', views.EcApiGroupViewSet.as_view({'get': 'list'}), name='get_ec_api_group'),
path('get_params_by_type', views.get_api_params_by_api_type),
path('get_url', views.general_api_url),
path('send_request', views.send_request),
path('get_suggest_params', views.get_suggest_params_by_api),
path('get_suggest_params_timestamp', views.get_suggest_params_timestamp_by_api),
path('set_user_data', views.set_user_select_data),
path('clear_user_data', views.clear_user_select_data),
path('get_quan', views.get_quan),
]

@ -1,41 +0,0 @@
from dspt_api.util.general.handle_redis import get_data_from_redis
from dspt_api.util.general.goods_list import get_goods_list
import random
class ApiCinemaGoodsPic(object):
def __init__(self, **kwargs):
self.member_type = kwargs.get('member_type')
self.api = kwargs.get('api')
self.ip = kwargs.get('ip')
self.env = kwargs.get('env')
self.cid = kwargs.get('cid')
self.pid = kwargs.get('pid')
def get_suggestion(self):
# play_id play_update_time
request_api = {'name': '3.2.1 获取卖品列表', 'path': 'cinema/goods'}
redis_key_api = f'dspt_api_{self.ip}_{self.env}_{self.member_type}_{self.pid}_{self.cid}_{request_api["path"]}'
result, _format, redis_data, _timestamp = get_data_from_redis(redis_key_api)
if result:
goods_list = get_goods_list(redis_data, _format)
goods = random.choice(goods_list)
goods_id = goods['id']
goods_type = goods['type']
return [
{'param': 'goods_id', 'value': goods_id, 'is_checked': True, 'result': True, 'timestamp': _timestamp},
{'param': 'type', 'value': goods_type, 'is_checked': True, 'result': True, 'timestamp': _timestamp}]
else:
# 返回推荐参数应该包含参数名,参数值,和是否勾选的状态
return [
{'param': 'goods_id', 'value': redis_data + request_api["name"], 'is_checked': True, 'result': False,
'timestamp': _timestamp},
{'param': 'type', 'value': redis_data + request_api["name"], 'is_checked': True, 'result': False,
'timestamp': _timestamp}]
def get_timestamp(self):
# play_id play_update_time
request_api = {'name': '3.2.1 获取卖品列表', 'path': 'cinema/goods'}
redis_key_api = f'dspt_api_{self.ip}_{self.env}_{self.member_type}_{self.pid}_{self.cid}_{request_api["path"]}'
result, _format, redis_data, _timestamp = get_data_from_redis(redis_key_api)
return _timestamp if result else 0

@ -1,33 +0,0 @@
from dspt_api.util.general.handle_redis import get_data_from_redis
import random
class ApiCinemaHallSeats:
def __init__(self, **kwargs):
self.member_type = kwargs.get('member_type')
self.api = kwargs.get('api')
self.ip = kwargs.get('ip')
self.env = kwargs.get('env')
self.cid = kwargs.get('cid')
self.pid = kwargs.get('pid')
def get_suggestion(self):
# hall_id
request_api = {'name': '3.1.3 获取影厅列表', 'path': 'cinema/halls'}
redis_key_api = f'dspt_api_{self.ip}_{self.env}_{self.member_type}_{self.pid}_{self.cid}_{request_api["path"]}'
result, _format, hall_data, _timestamp = get_data_from_redis(redis_key_api)
if result:
hall_id = hall_data['id']
return [{'param': 'hall_id', 'value': hall_id, 'is_checked': True, 'result': True, 'timestamp': _timestamp}]
else:
# 返回推荐参数应该包含参数名,参数值,和是否勾选的状态
return [
{'param': 'hall_id', 'value': hall_data + request_api["name"], 'is_checked': True, 'result': False,
'timestamp': _timestamp}]
def get_timestamp(self):
# hall_id
request_api = {'name': '3.1.3 获取影厅列表', 'path': 'cinema/halls'}
redis_key_api = f'dspt_api_{self.ip}_{self.env}_{self.member_type}_{self.pid}_{self.cid}_{request_api["path"]}'
result, _format, hall_data, _timestamp = get_data_from_redis(redis_key_api)
return _timestamp if result else 0

@ -1,29 +0,0 @@
from dspt_api.util.general.handle_redis import get_data_from_redis
import datetime
class ApiCinemaPlaysIncrement:
def __init__(self, **kwargs):
self.member_type = kwargs.get('member_type')
self.api = kwargs.get('api')
self.ip = kwargs.get('ip')
self.env = kwargs.get('env')
self.cid = kwargs.get('cid')
self.pid = kwargs.get('pid')
def get_suggestion(self):
# start
request_api = {'name': '3.1.6 获取放映计划列表(增量)', 'path': 'cinema/plays-increment'}
redis_key_api = f'dspt_api_{self.ip}_{self.env}_{self.member_type}_{self.pid}_{self.cid}_{request_api["path"]}'
result, _format, redis_data, _timestamp = get_data_from_redis(redis_key_api)
# 生成默认值
start = redis_data['nextSyncStartTime'] if result else datetime.datetime.strftime(datetime.datetime.now(),
'%Y-%m-%d') + ' 06:00:00'
return [{'param': 'start', 'value': start, 'is_checked': True, 'result': True, 'timestamp': _timestamp}]
def get_timestamp(self):
# start
request_api = {'name': '3.1.6 获取放映计划列表(增量)', 'path': 'cinema/plays-increment'}
redis_key_api = f'dspt_api_{self.ip}_{self.env}_{self.member_type}_{self.pid}_{self.cid}_{request_api["path"]}'
result, _format, redis_data, _timestamp = get_data_from_redis(redis_key_api)
return _timestamp if result else 0

@ -1,53 +0,0 @@
import time
from dspt_api.util.general.handle_redis import get_data_from_redis
from dspt_api.util.general.handle_ecard import get_ecard
class ApiEcardDetail:
def __init__(self, **kwargs):
self.member_type = kwargs.get('member_type')
self.api = kwargs.get('api')
self.ip = kwargs.get('ip')
self.env = kwargs.get('env')
self.cid = kwargs.get('cid')
self.pid = kwargs.get('pid')
def get_suggestion(self):
_now = int(time.time() * 1000)
# 获取本地记录的联名卡
if ecard_num := get_ecard(self.ip, self.env, self.pid, self.cid):
return [{'param': 'ecard_number', 'value': ecard_num,'is_checked': True, 'result': True,'timestamp': _now}]
# ecard_number
request_api_ec_1 = {'name': '3.4.4 获取联名卡详情', 'path': 'ecard/detail'}
redis_key_api_ec_1 = f'dspt_api_{self.ip}_{self.env}_{self.member_type}_{self.pid}_{self.cid}_{request_api_ec_1["path"]}'
request_api_ec_2 = {'name': '3.4.2 联名卡开卡', 'path': 'ecard/regist'}
redis_key_api_ec_2 = f'dspt_api_{self.ip}_{self.env}_{self.member_type}_{self.pid}_{self.cid}_{request_api_ec_2["path"]}'
result_ec_1, _format_ec_1, redis_data_ec_1, _timestamp_ec_1 = get_data_from_redis(redis_key_api_ec_1)
result_ec_2, _format_ec_2, redis_data_ec_2, _timestamp_ec_2 = get_data_from_redis(redis_key_api_ec_2)
ecard_number_result = False
ecard_number = False
if result_ec_2:
print('redis_data_ec_2', redis_data_ec_2)
ecard_number_ec_2 = {'param': 'ecard_number', 'value': redis_data_ec_2['ecardNumber'],
'is_checked': True, 'result': True,
'timestamp': _timestamp_ec_2}
ecard_number = ecard_number_ec_2
ecard_number_result = True
if result_ec_1:
ecard_number_ec_1 = {'param': 'ecard_number', 'value': redis_data_ec_1['ecardNumber'],
'is_checked': True, 'result': True,
'timestamp': _timestamp_ec_1}
ecard_number = ecard_number_ec_1
ecard_number_result = True
if result_ec_1 and result_ec_2:
ecard_number = ecard_number_ec_1 if _timestamp_ec_1 >= _timestamp_ec_2 else ecard_number_ec_2
if ecard_number_result:
return [ecard_number]
else:
return [{'param': 'ecard_number', 'value': redis_data_ec_1 + request_api_ec_1["name"], 'is_checked': True,
'result': True,
'timestamp': _now},]
def get_timestamp(self):
return int(time.time() * 1000)

@ -1,62 +0,0 @@
import time
from django_redis import get_redis_connection
from dspt_api.util.general.handle_redis import get_data_from_redis
class ApiEcardOrderDetail:
def __init__(self, **kwargs):
self.member_type = kwargs.get('member_type')
self.api = kwargs.get('api')
self.ip = kwargs.get('ip')
self.env = kwargs.get('env')
self.cid = kwargs.get('cid')
self.pid = kwargs.get('pid')
def get_suggestion(self):
_now = int(time.time() * 1000)
# partner_order_no
request_renew = {'name': '3.4.3 联名卡续卡', 'path': 'ecard/renew'}
redis_key_renew_order_num = f'dspt_api_{self.ip}_{self.env}_{self.member_type}_{self.pid}_{self.cid}_{request_renew["path"]}_order_num'
redis_key_renew = f'dspt_api_{self.ip}_{self.env}_{self.member_type}_{self.pid}_{self.cid}_{request_renew["path"]}'
request_regist = {'name': '3.4.2 联名卡开卡', 'path': 'ecard/regist'}
redis_key_regist_order_num = f'dspt_api_{self.ip}_{self.env}_{self.member_type}_{self.pid}_{self.cid}_{request_regist["path"]}_order_num'
redis_key_regist = f'dspt_api_{self.ip}_{self.env}_{self.member_type}_{self.pid}_{self.cid}_{request_regist["path"]}'
result_renew, _format__renew, redis_data_renew, _timestamp_renew = get_data_from_redis(redis_key_renew)
result_regist, _format_regist, redis_data_regist, _timestamp_regist = get_data_from_redis(redis_key_regist)
redis_conn = get_redis_connection()
order_num_renew = redis_conn.get(redis_key_renew_order_num)
print('order_num_renew', order_num_renew)
order_num_regist = redis_conn.get(redis_key_regist_order_num)
print('order_num_regist', order_num_regist)
order_num_result = [
{'param': 'partner_order_no', 'value': '请手动输入参数!', 'is_checked': True, 'result': True,
'timestamp': _now},
{'param': 'order_type', 'value': '请手动输入参数!', 'is_checked': True, 'result': True, 'timestamp': _now}]
if order_num_regist:
order_num_result_regist = [
{'param': 'partner_order_no', 'value': str(order_num_regist, encoding='utf-8'), 'is_checked': True,
'result': True, 'timestamp': _now},
{'param': 'order_type', 'value': '1', 'is_checked': True, 'result': True, 'timestamp': _now}]
if order_num_renew:
order_num_result_renew = [
{'param': 'partner_order_no', 'value': str(order_num_renew, encoding='utf-8'), 'is_checked': True,
'result': True,
'timestamp': _now},
{'param': 'order_type', 'value': '2', 'is_checked': True, 'result': True, 'timestamp': _now}]
if order_num_renew:
order_num_result = order_num_result_renew
if order_num_regist:
order_num_result = order_num_result_regist
if order_num_renew and order_num_regist:
order_num_result = order_num_result_regist if _timestamp_regist > _timestamp_renew else order_num_result_renew
return order_num_result
def get_timestamp(self):
return int(time.time() * 1000)

@ -1,30 +0,0 @@
import time
from django_redis import get_redis_connection
from dspt_api.util.general.get_order_num import general_order_num
from dspt_api.util.general.handle_redis import get_data_from_redis
from dspt_api.util.api.ecard_order_detail import ApiEcardOrderDetail
from dspt_api.util.general.handle_ecard import get_ecard
class ApiEcardRefund:
def __init__(self, **kwargs):
self.member_type = kwargs.get('member_type')
self.api = kwargs.get('api')
self.ip = kwargs.get('ip')
self.env = kwargs.get('env')
self.cid = kwargs.get('cid')
self.pid = kwargs.get('pid')
self.kwargs = kwargs
def get_suggestion(self):
# source_order_no
source_order_no = ApiEcardOrderDetail(**self.kwargs).get_suggestion()[0]
# partner_order_no
order_num = general_order_num('REF', self.api, self.member_type, self.ip, self.env, self.pid, self.cid)
return [{'param': 'source_order_no', 'value': source_order_no['value'], 'is_checked': True, 'result': True,
'timestamp': int(time.time() * 1000)},
{'param': 'partner_order_no', 'value': order_num, 'is_checked': True, 'result': True,
'timestamp': int(time.time() * 1000)}]
def get_timestamp(self):
return int(time.time() * 1000)

@ -1,45 +0,0 @@
from dspt_api.util.general.handle_redis import get_data_from_redis
from dspt_api.util.general.get_order_num import general_order_num
import time
import random
class ApiEcardRegist:
def __init__(self, **kwargs):
self.member_type = kwargs.get('member_type')
self.api = kwargs.get('api')
self.ip = kwargs.get('ip')
self.env = kwargs.get('env')
self.cid = kwargs.get('cid')
self.pid = kwargs.get('pid')
def get_suggestion(self):
request_api = {'name': '3.4.1 获取联名卡等级', 'path': 'ecard/ecard-levels'}
redis_key_api = f'dspt_api_{self.ip}_{self.env}_{self.member_type}_{self.pid}_{self.cid}_{request_api["path"]}'
result, _format, level_data, _timestamp = get_data_from_redis(redis_key_api)
if result:
level_no = level_data['ecardLevelNo']
fee = level_data['registerFee']
order_num = general_order_num('REG', self.api, self.member_type, self.ip, self.env, self.pid, self.cid)
return [
{'param': 'mobile', 'value': 18688886666, 'is_checked': True, 'result': True, 'timestamp': _timestamp},
{'param': 'register_fee', 'value': fee, 'is_checked': True, 'result': True, 'timestamp': _timestamp},
{'param': 'ecard_level_no', 'value': level_no, 'is_checked': True, 'result': True,
'timestamp': _timestamp},
{'param': 'partner_order_no', 'value': order_num, 'is_checked': True, 'result': True,
'timestamp': _timestamp}]
else:
# 返回推荐参数应该包含参数名,参数值,和是否勾选的状态
return [
{'param': 'mobile', 'value': 18688886666, 'is_checked': True, 'result': True, 'timestamp': _timestamp},
{'param': 'register_fee', 'value': level_data + request_api["name"], 'is_checked': True, 'result': True,
'timestamp': _timestamp},
{'param': 'ecard_level_no', 'value': level_data + request_api["name"], 'is_checked': True,
'result': True,
'timestamp': _timestamp},
{'param': 'partner_order_no', 'value': '', 'is_checked': True, 'result': True,
'timestamp': _timestamp}
]
def get_timestamp(self):
return int(time.time() * 1000)

@ -1,83 +0,0 @@
import random
import time
from dspt_api.util.general.get_order_num import general_order_num
from dspt_api.util.general.handle_redis import get_data_from_redis
from dspt_api.util.general.handle_ecard import get_ecard, get_ecard_renew_fee
class ApiEcardRenew:
def __init__(self, **kwargs):
self.member_type = kwargs.get('member_type')
self.api = kwargs.get('api')
self.ip = kwargs.get('ip')
self.env = kwargs.get('env')
self.cid = kwargs.get('cid')
self.pid = kwargs.get('pid')
def get_suggestion(self):
_now = int(time.time() * 1000)
# ecard_number
# 获取本地记录的联名卡
ecard_number_result = False
ecard_number = False
if ecard_num := get_ecard(self.ip, self.env, self.pid, self.cid):
ecard_number = {'param': 'ecard_number', 'value': ecard_num, 'is_checked': True, 'result': True,
'timestamp': _now}
ecard_number_result = True
else:
request_api_ec_1 = {'name': '3.4.4 获取联名卡详情', 'path': 'ecard/detail'}
redis_key_api_ec_1 = f'dspt_api_{self.ip}_{self.env}_{self.member_type}_{self.pid}_{self.cid}_{request_api_ec_1["path"]}'
request_api_ec_2 = {'name': '3.4.2 联名卡开卡', 'path': 'ecard/regist'}
redis_key_api_ec_2 = f'dspt_api_{self.ip}_{self.env}_{self.member_type}_{self.pid}_{self.cid}_{request_api_ec_2["path"]}'
result_ec_1, _format_ec_1, redis_data_ec_1, _timestamp_ec_1 = get_data_from_redis(redis_key_api_ec_1)
result_ec_2, _format_ec_2, redis_data_ec_2, _timestamp_ec_2 = get_data_from_redis(redis_key_api_ec_2)
if result_ec_2:
print('redis_data_ec_2', redis_data_ec_2)
ecard_number_ec_2 = {'param': 'ecard_number', 'value': redis_data_ec_2['ecardNumber'],
'is_checked': True, 'result': True,
'timestamp': _timestamp_ec_2}
ecard_number = ecard_number_ec_2
ecard_number_result = True
if result_ec_1:
ecard_number_ec_1 = {'param': 'ecard_number', 'value': redis_data_ec_1['ecardNumber'],
'is_checked': True, 'result': True,
'timestamp': _timestamp_ec_1}
ecard_number = ecard_number_ec_1
ecard_number_result = True
if result_ec_1 and result_ec_2:
ecard_number = ecard_number_ec_1 if _timestamp_ec_1 >= _timestamp_ec_2 else ecard_number_ec_2
# renew_fee
result_renew_fee = False
if ecard_number is not False:
fee = get_ecard_renew_fee(ecard_number['value'])
if fee is not None:
renew_fee = {'param': 'renew_fee', 'value': fee,
'is_checked': True, 'result': True,
'timestamp': _now}
result_renew_fee = True
else:
renew_fee = {'param': 'renew_fee', 'value': '此卡级别不能续卡',
'is_checked': True, 'result': True,
'timestamp': _now}
result_renew_fee = True
# partner_order_no
order_num = general_order_num('REN', self.api, self.member_type, self.ip, self.env, self.pid, self.cid)
partner_order_no = {'param': 'partner_order_no', 'value': order_num, 'is_checked': True, 'result': True,
'timestamp': _now}
if ecard_number_result and result_renew_fee:
return [ecard_number, renew_fee, partner_order_no]
else:
return [{'param': 'ecard_number', 'value': redis_data_ec_1 + request_api_ec_1["name"], 'is_checked': True,
'result': True,
'timestamp': _now},
{'param': 'renew_fee', 'value': '请手动输入参数!', 'is_checked': True, 'result': True,
'timestamp': _now},
partner_order_no
]
def get_timestamp(self):
return int(time.time() * 1000)

@ -1,29 +0,0 @@
from dspt_api.util.general.handle_redis import get_data_from_redis
from dspt_api.util.api.seat_lock import ApiSeatLock
from dspt_api.util.api.ecard_detail import ApiEcardDetail
import random
class ApiEcardSeatPrice:
def __init__(self, **kwargs):
self.member_type = kwargs.get('member_type')
self.api = kwargs.get('api')
self.ip = kwargs.get('ip')
self.env = kwargs.get('env')
self.cid = kwargs.get('cid')
self.pid = kwargs.get('pid')
self.kwargs = kwargs
def get_suggestion(self):
# 获取 play_id seat_idplay_update_time
params = ApiSeatLock(**self.kwargs).get_suggestion()
# 获取 ecard_number
ecard_number = ApiEcardDetail(**self.kwargs).get_suggestion()
return params + ecard_number
def get_timestamp(self):
# 获取 play_id seat_idplay_update_time
params_ts = ApiSeatLock(**self.kwargs).get_timestamp()
# 获取 ecard_number
ecard_number_ts = ApiEcardDetail(**self.kwargs).get_timestamp()
return params_ts if params_ts > ecard_number_ts else ecard_number_ts

@ -1,52 +0,0 @@
import json
from dspt_api.util.general.handle_redis import get_data_from_redis
from dspt_api.util.general.get_order_num import general_order_num
import time
import random
"""
UPDATE cinema_common_info SET cinema_common_info_val = '[{"channel_name":"ziying","shelf_id":"1"}]' WHERE cinema_common_info_key = 'third_channel_autosell_config';
"""
class ApiGoodsDeduct:
def __init__(self, **kwargs):
self.member_type = kwargs.get('member_type')
self.api = kwargs.get('api')
self.ip = kwargs.get('ip')
self.env = kwargs.get('env')
self.cid = kwargs.get('cid')
self.pid = kwargs.get('pid')
self.user_data = {
'ip': self.ip,
'env': self.env,
'member_type': self.member_type,
'pid': self.pid,
'cid': self.cid,
}
self.return_data = []
def get_suggestion(self):
print('get_suggestion', self.user_data)
self.handle()
return self.return_data
@staticmethod
def get_timestamp():
return int(time.time() * 1000)
def handle(self):
# 获取 ticket_flag
redis_key_prefix = f'dspt_api_{self.ip}_{self.env}_{self.member_type}_{self.pid}_{self.cid}'
request_api_lock_buy = {'name': '3.3.3 混合下单(影票、卖品)', 'path': 'seat/lock-buy'}
redis_key_api_lock_buy = f'{redis_key_prefix}_{request_api_lock_buy["path"]}'
result_lock_buy, _format_lock_buy, ticket_flag_lock_buy, _timestamp_lock_buy = get_data_from_redis(
redis_key_api_lock_buy)
if not result_lock_buy:
self.add_param('center_flag', '请手动输入参数,或先请求接口:3.3.3 混合下单(影票、卖品)')
self.add_param('center_flag', ticket_flag_lock_buy['ticketFlag1'] + ticket_flag_lock_buy['ticketFlag2'])
def add_param(self, field, value, is_checked=True, result=True, timestamp=int(time.time() * 1000)):
self.return_data.append(
{'param': field, 'value': value, 'is_checked': is_checked, 'result': result, 'timestamp': timestamp})

@ -1,66 +0,0 @@
from dspt_api.util.general.handle_redis import get_data_from_redis
from dspt_api.util.general.get_order_num import general_order_num
from dspt_api.util.general.handle_goods import general_goods_params
from dspt_api.util.general.handle_ecard import get_ecard
import time
import random
import json
class ApiOrderBuyGoods:
def __init__(self, **kwargs):
self.member_type = kwargs.get('member_type')
self.api = kwargs.get('api')
self.ip = kwargs.get('ip')
self.env = kwargs.get('env')
self.cid = kwargs.get('cid')
self.pid = kwargs.get('pid')
self.sale_type = kwargs.get('sale_type')
self.pay_type = kwargs.get('pay_type')
self.user_data = {
'ip': self.ip,
'env': self.env,
'member_type': self.member_type,
'pid': self.pid,
'cid': self.cid,
}
self.return_data = []
def get_suggestion(self):
# 通用字段
self.add_param('mobile', '18688886666', timestamp=1000000000000)
_partner_buy_ticket_id = general_order_num('BUY_G', self.api, self.member_type, self.ip, self.env, self.pid,
self.cid)
self.add_param('partner_buy_ticket_id', _partner_buy_ticket_id)
# 联名卡卡号
ecard_num = None
if self.pay_type == 'ecard':
ecard_num = get_ecard(self.ip, self.env, self.pid, self.cid)
self.add_param('ecard_number', ecard_num, timestamp=1000000000000)
self.goods()
return self.return_data
@staticmethod
def get_timestamp():
return int(time.time() * 1000)
def goods(self):
delivery_appoint_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time() + 5 * 60))
_good_result, _goods_field, _goods_cash, _quan, _goods_timestamp = general_goods_params(self.pay_type,
self.user_data)
if _good_result is False:
self.add_param('goods', '请手动输入参数,或先请求接口:3.2.1 获取卖品列表', timestamp=_goods_timestamp)
self.add_param('cash', '请手动输入参数,或先请求接口:3.2.1 获取卖品列表', timestamp=_goods_timestamp)
return False
self.add_param('goods', json.dumps(_goods_field), timestamp=_goods_timestamp)
self.add_param('cash', _goods_cash, timestamp=_goods_timestamp)
self.add_param('delivery_type', '2', is_checked=False, timestamp=_goods_timestamp)
self.add_param('delivery_location', '1号厅', is_checked=False, timestamp=_goods_timestamp)
self.add_param('delivery_appoint_time', delivery_appoint_time, is_checked=False, timestamp=_goods_timestamp)
self.add_param('contact_number', '18688886666', is_checked=False, timestamp=_goods_timestamp)
def add_param(self, field, value, is_checked=True, result=True, timestamp=int(time.time() * 1000)):
self.return_data.append(
{'param': field, 'value': value, 'is_checked': is_checked, 'result': result, 'timestamp': timestamp})

@ -1,4 +0,0 @@
from dspt_api.util.api.order_ticket_flag import ApiOrderTicketFlag
class ApiOrderInfo(ApiOrderTicketFlag):
pass

@ -1,46 +0,0 @@
import json
from dspt_api.util.general.handle_redis import get_param_from_redis
from dspt_api.util.general.get_order_num import general_order_num
import time
import random
class ApiOrderStatus:
def __init__(self, **kwargs):
self.member_type = kwargs.get('member_type')
self.api = kwargs.get('api')
self.ip = kwargs.get('ip')
self.env = kwargs.get('env')
self.cid = kwargs.get('cid')
self.pid = kwargs.get('pid')
self.user_data = {
'ip': self.ip,
'env': self.env,
'member_type': self.member_type,
'pid': self.pid,
'cid': self.cid,
}
self.return_data = []
def get_suggestion(self):
print('get_suggestion', self.user_data)
self.handle()
return self.return_data
@staticmethod
def get_timestamp():
return int(time.time() * 1000)
def handle(self):
# 获取 ticket_flag
redis_key_prefix = f'dspt_api_{self.ip}_{self.env}_{self.member_type}_{self.pid}_{self.cid}'
request_api_lock_buy = {'name': '3.3.3 混合下单(影票、卖品)', 'path': 'seat/lock-buy'}
redis_key_api_lock_buy = f'{redis_key_prefix}_{request_api_lock_buy["path"]}'
result_lock_buy = get_param_from_redis(redis_key_api_lock_buy)
if not result_lock_buy:
self.add_param('partner_order_id', '请手动输入参数,或先请求接口:3.3.3 混合下单(影票、卖品)')
self.add_param('partner_order_id', result_lock_buy['partner_buy_ticket_id'])
def add_param(self, field, value, is_checked=True, result=True, timestamp=int(time.time() * 1000)):
self.return_data.append(
{'param': field, 'value': value, 'is_checked': is_checked, 'result': result, 'timestamp': timestamp})

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save