Factory.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. <?php
  2. namespace app\common\model\ps;
  3. use app\common\model\User;
  4. use fast\Random;
  5. use think\Db;
  6. use think\Exception;
  7. use think\Model;
  8. /**
  9. * 工厂
  10. */
  11. class Factory extends Model
  12. {
  13. protected $name = 'ps_factory';
  14. protected $autoWriteTimestamp = 'int';
  15. protected $createTime = 'createtime';
  16. protected $updateTime = 'updatetime';
  17. /**
  18. * 会员未入厂时:有邀请码则加入,否则创建工厂当管理员。
  19. * ThinkPHP 5 的 Config::get 只支持两级键,不能用 ps.factory.register_create_factory。
  20. * @param User $user
  21. * @param string $inviteCode
  22. * @param string $factoryName 注册开厂时必填,不用昵称拼「某某的工厂」
  23. * @return Factory|null
  24. * @throws Exception
  25. */
  26. public static function ensureBound(User $user, $inviteCode = '', $factoryName = '')
  27. {
  28. if ((int)$user->factory_id > 0) {
  29. return self::get($user->factory_id);
  30. }
  31. $inviteCode = strtoupper(trim((string)$inviteCode));
  32. if ($inviteCode !== '') {
  33. return self::joinByInvite($user, $inviteCode);
  34. }
  35. $factoryCfg = \think\Config::get('ps.factory');
  36. $autoCreate = true;
  37. if (is_array($factoryCfg) && array_key_exists('register_create_factory', $factoryCfg)) {
  38. $autoCreate = (bool)$factoryCfg['register_create_factory'];
  39. }
  40. if (!$autoCreate) {
  41. return null;
  42. }
  43. return self::createForOwner($user, $factoryName);
  44. }
  45. /**
  46. * 为新注册用户创建工厂并设为管理员
  47. * @param User $user
  48. * @param string $factoryName
  49. * @return Factory
  50. * @throws Exception
  51. */
  52. public static function createForOwner(User $user, $factoryName = '')
  53. {
  54. $name = trim((string)$factoryName);
  55. if ($name === '') {
  56. throw new Exception('请填写工厂名称');
  57. }
  58. if (mb_strlen($name) > 100) {
  59. throw new Exception('工厂名称不能超过100个字');
  60. }
  61. $scoreCfg = \think\Config::get('ps.score') ?: [];
  62. $gift = isset($scoreCfg['register_gift']) ? (int)$scoreCfg['register_gift'] : 0;
  63. if ($gift < 0) {
  64. $gift = 0;
  65. }
  66. $factory = self::create([
  67. 'name' => $name,
  68. 'code' => 'F' . date('ymd') . $user->id,
  69. 'invite_code' => self::uniqueInviteCode(),
  70. 'owner_user_id' => $user->id,
  71. 'score' => $gift,
  72. 'status' => 'normal',
  73. ]);
  74. $user->save([
  75. 'factory_id' => $factory->id,
  76. 'factory_role' => 'owner',
  77. ]);
  78. return $factory;
  79. }
  80. /**
  81. * 凭邀请码加入工厂(操作员)
  82. * @param User $user
  83. * @param string $inviteCode
  84. * @return Factory
  85. * @throws Exception
  86. */
  87. public static function joinByInvite(User $user, $inviteCode)
  88. {
  89. $factory = self::where('invite_code', strtoupper(trim($inviteCode)))
  90. ->where('status', 'normal')
  91. ->find();
  92. if (!$factory) {
  93. throw new Exception('邀请码无效');
  94. }
  95. $user->save([
  96. 'factory_id' => $factory->id,
  97. 'factory_role' => 'operator',
  98. ]);
  99. return $factory;
  100. }
  101. /**
  102. * 变更工厂积分(行锁)
  103. * @param int $factoryId
  104. * @param int $score 正加负减
  105. * @param string $bizType
  106. * @param int $bizId
  107. * @param string $memo
  108. * @param int $operatorUserId
  109. * @return Factory
  110. * @throws Exception
  111. */
  112. public static function changeScore($factoryId, $score, $bizType, $bizId, $memo, $operatorUserId = 0)
  113. {
  114. if ((int)$score === 0) {
  115. return self::get($factoryId);
  116. }
  117. Db::startTrans();
  118. try {
  119. $factory = self::lock(true)->find($factoryId);
  120. if (!$factory) {
  121. throw new Exception('工厂不存在');
  122. }
  123. $before = (int)$factory->score;
  124. $after = $before + (int)$score;
  125. if ($after < 0) {
  126. throw new Exception('工厂积分不足');
  127. }
  128. $factory->save(['score' => $after]);
  129. FactoryScoreLog::create([
  130. 'factory_id' => $factoryId,
  131. 'operator_user_id' => $operatorUserId,
  132. 'score' => $score,
  133. 'before' => $before,
  134. 'after' => $after,
  135. 'biz_type' => $bizType,
  136. 'biz_id' => $bizId,
  137. 'memo' => $memo,
  138. ]);
  139. Db::commit();
  140. return $factory;
  141. } catch (\Exception $e) {
  142. Db::rollback();
  143. throw $e;
  144. }
  145. }
  146. protected static function uniqueInviteCode()
  147. {
  148. do {
  149. $code = strtoupper(Random::alnum(8));
  150. } while (self::where('invite_code', $code)->find());
  151. return $code;
  152. }
  153. }