[会员管理]-移除
This commit is contained in:
@@ -1,150 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\admin\controller\user;
|
||||
|
||||
use Throwable;
|
||||
use app\admin\model\UserRule;
|
||||
use app\admin\model\UserGroup;
|
||||
use app\common\controller\Backend;
|
||||
use Webman\Http\Request;
|
||||
use support\Response;
|
||||
|
||||
class Group extends Backend
|
||||
{
|
||||
protected ?object $model = null;
|
||||
|
||||
protected array|string $preExcludeFields = ['update_time', 'create_time'];
|
||||
protected array|string $quickSearchField = 'name';
|
||||
|
||||
protected function initController(Request $request): ?Response
|
||||
{
|
||||
$this->model = new UserGroup();
|
||||
return null;
|
||||
}
|
||||
|
||||
public function select(Request $request): Response
|
||||
{
|
||||
$response = $this->initializeBackend($request);
|
||||
if ($response !== null) return $response;
|
||||
|
||||
list($where, $alias, $limit, $order) = $this->queryBuilder();
|
||||
$data = $this->model
|
||||
->alias($alias)
|
||||
->where($where)
|
||||
->order($order)
|
||||
->limit(9999)
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
return $this->success('', [
|
||||
'options' => $data,
|
||||
]);
|
||||
}
|
||||
|
||||
public function add(Request $request): Response
|
||||
{
|
||||
$response = $this->initializeBackend($request);
|
||||
if ($response !== null) return $response;
|
||||
|
||||
if ($request->method() !== 'POST') {
|
||||
return $this->error(__('Parameter error'));
|
||||
}
|
||||
|
||||
$data = $request->post();
|
||||
if (!$data) {
|
||||
return $this->error(__('Parameter %s can not be empty', ['']));
|
||||
}
|
||||
|
||||
$data = $this->excludeFields($data);
|
||||
$data = $this->handleRules($data);
|
||||
|
||||
$result = false;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
if ($this->modelValidate) {
|
||||
$validateClass = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
if (class_exists($validateClass)) {
|
||||
$validate = new $validateClass();
|
||||
$validate->scene('add')->check($data);
|
||||
}
|
||||
}
|
||||
$result = $this->model->save($data);
|
||||
$this->model->commit();
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
return $this->error($e->getMessage());
|
||||
}
|
||||
return $result !== false ? $this->success(__('Added successfully')) : $this->error(__('No rows were added'));
|
||||
}
|
||||
|
||||
public function edit(Request $request): Response
|
||||
{
|
||||
$response = $this->initializeBackend($request);
|
||||
if ($response !== null) return $response;
|
||||
|
||||
$pk = $this->model->getPk();
|
||||
$id = $request->post($pk) ?? $request->get($pk);
|
||||
$row = $this->model->find($id);
|
||||
if (!$row) {
|
||||
return $this->error(__('Record not found'));
|
||||
}
|
||||
|
||||
if ($request->method() === 'POST') {
|
||||
$data = $request->post();
|
||||
if (!$data) {
|
||||
return $this->error(__('Parameter %s can not be empty', ['']));
|
||||
}
|
||||
$data = $this->excludeFields($data);
|
||||
$data = $this->handleRules($data);
|
||||
$result = false;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
if ($this->modelValidate) {
|
||||
$validateClass = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
if (class_exists($validateClass)) {
|
||||
$validate = new $validateClass();
|
||||
$validate->scene('edit')->check(array_merge($data, [$pk => $row[$pk]]));
|
||||
}
|
||||
}
|
||||
$result = $row->save($data);
|
||||
$this->model->commit();
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
return $this->error($e->getMessage());
|
||||
}
|
||||
return $result !== false ? $this->success(__('Update successful')) : $this->error(__('No rows updated'));
|
||||
}
|
||||
|
||||
$pidArr = UserRule::field('pid')->distinct(true)->where('id', 'in', $row->rules)->select()->toArray();
|
||||
$rules = $row->rules ? explode(',', $row->rules) : [];
|
||||
foreach ($pidArr as $item) {
|
||||
$ruKey = array_search($item['pid'], $rules);
|
||||
if ($ruKey !== false) {
|
||||
unset($rules[$ruKey]);
|
||||
}
|
||||
}
|
||||
$rowData = $row->toArray();
|
||||
$rowData['rules'] = array_values($rules);
|
||||
return $this->success('', ['row' => $rowData]);
|
||||
}
|
||||
|
||||
private function handleRules(array $data): array
|
||||
{
|
||||
if (isset($data['rules']) && is_array($data['rules']) && $data['rules']) {
|
||||
$rules = UserRule::select();
|
||||
$super = true;
|
||||
foreach ($rules as $rule) {
|
||||
if (!in_array($rule['id'], $data['rules'])) {
|
||||
$super = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$data['rules'] = $super ? '*' : implode(',', $data['rules']);
|
||||
} else {
|
||||
unset($data['rules']);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\admin\controller\user;
|
||||
|
||||
use app\admin\model\User;
|
||||
use app\admin\model\UserMoneyLog;
|
||||
use app\common\controller\Backend;
|
||||
use Webman\Http\Request;
|
||||
use support\Response;
|
||||
|
||||
class MoneyLog extends Backend
|
||||
{
|
||||
protected ?object $model = null;
|
||||
|
||||
protected array $withJoinTable = ['user'];
|
||||
protected array|string $preExcludeFields = ['create_time'];
|
||||
protected array|string $quickSearchField = ['user.username', 'user.nickname'];
|
||||
|
||||
protected function initController(Request $request): ?Response
|
||||
{
|
||||
$this->model = new UserMoneyLog();
|
||||
return null;
|
||||
}
|
||||
|
||||
public function add(Request $request): Response
|
||||
{
|
||||
$response = $this->initializeBackend($request);
|
||||
if ($response !== null) return $response;
|
||||
|
||||
if ($request->method() === 'POST') {
|
||||
return $this->_add();
|
||||
}
|
||||
|
||||
$userId = $request->get('userId', $request->post('userId', 0));
|
||||
$user = User::where('id', $userId)->find();
|
||||
if (!$user) {
|
||||
return $this->error(__("The user can't find it"));
|
||||
}
|
||||
return $this->success('', ['user' => $user]);
|
||||
}
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\admin\controller\user;
|
||||
|
||||
use ba\Tree;
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\model\UserRule;
|
||||
use Webman\Http\Request;
|
||||
use support\Response;
|
||||
|
||||
class Rule extends Backend
|
||||
{
|
||||
protected ?object $model = null;
|
||||
protected Tree $tree;
|
||||
protected array $initValue = [];
|
||||
protected bool $assembleTree = true;
|
||||
protected string $keyword = '';
|
||||
|
||||
protected array|string $preExcludeFields = ['create_time', 'update_time'];
|
||||
protected array|string $defaultSortField = ['weigh' => 'desc'];
|
||||
protected array|string $quickSearchField = 'title';
|
||||
|
||||
protected function initController(Request $request): ?Response
|
||||
{
|
||||
$this->model = new UserRule();
|
||||
$this->tree = Tree::instance();
|
||||
$isTree = filter_var($request->get('isTree', $request->post('isTree', true)), FILTER_VALIDATE_BOOLEAN);
|
||||
$initValue = $request->get('initValue') ?? $request->post('initValue') ?? [];
|
||||
$this->initValue = is_array($initValue) ? array_filter($initValue) : [];
|
||||
$this->keyword = $request->get('quickSearch', $request->post('quickSearch', ''));
|
||||
$this->assembleTree = $isTree && !$this->initValue;
|
||||
return null;
|
||||
}
|
||||
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
$response = $this->initializeBackend($request);
|
||||
if ($response !== null) return $response;
|
||||
|
||||
if ($request->get('select') || $request->post('select')) {
|
||||
return $this->select($request);
|
||||
}
|
||||
|
||||
list($where, , , ) = $this->queryBuilder();
|
||||
$list = $this->model->where($where)->order($this->defaultSortField)->select();
|
||||
|
||||
if ($this->assembleTree) {
|
||||
$list = $this->tree->assembleChild($list->toArray());
|
||||
} else {
|
||||
$list = $list->toArray();
|
||||
}
|
||||
|
||||
return $this->success('', [
|
||||
'list' => $list,
|
||||
'remark' => get_route_remark(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function add(Request $request): Response
|
||||
{
|
||||
$response = $this->initializeBackend($request);
|
||||
if ($response !== null) return $response;
|
||||
return $this->_add();
|
||||
}
|
||||
|
||||
public function edit(Request $request): Response
|
||||
{
|
||||
$response = $this->initializeBackend($request);
|
||||
if ($response !== null) return $response;
|
||||
return $this->_edit();
|
||||
}
|
||||
|
||||
public function del(Request $request): Response
|
||||
{
|
||||
$response = $this->initializeBackend($request);
|
||||
if ($response !== null) return $response;
|
||||
return $this->_del();
|
||||
}
|
||||
|
||||
public function select(Request $request): Response
|
||||
{
|
||||
$response = $this->initializeBackend($request);
|
||||
if ($response !== null) return $response;
|
||||
|
||||
list($where, , , ) = $this->queryBuilder();
|
||||
$list = $this->model->where($where)->order($this->defaultSortField)->select();
|
||||
|
||||
if ($this->assembleTree) {
|
||||
$list = $this->tree->assembleChild($list->toArray());
|
||||
} else {
|
||||
$list = $list->toArray();
|
||||
}
|
||||
|
||||
return $this->success('', ['list' => $list]);
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\admin\controller\user;
|
||||
|
||||
use app\admin\model\User;
|
||||
use app\admin\model\UserScoreLog;
|
||||
use app\common\controller\Backend;
|
||||
use Webman\Http\Request;
|
||||
use support\Response;
|
||||
|
||||
class ScoreLog extends Backend
|
||||
{
|
||||
protected ?object $model = null;
|
||||
|
||||
protected array $withJoinTable = ['user'];
|
||||
protected array|string $preExcludeFields = ['create_time'];
|
||||
protected array|string $quickSearchField = ['user.username', 'user.nickname'];
|
||||
|
||||
protected function initController(Request $request): ?Response
|
||||
{
|
||||
$this->model = new UserScoreLog();
|
||||
return null;
|
||||
}
|
||||
|
||||
public function add(Request $request): Response
|
||||
{
|
||||
$response = $this->initializeBackend($request);
|
||||
if ($response !== null) return $response;
|
||||
|
||||
if ($request->method() === 'POST') {
|
||||
return $this->_add();
|
||||
}
|
||||
|
||||
$userId = $request->get('userId', $request->post('userId', 0));
|
||||
$user = User::where('id', $userId)->find();
|
||||
if (!$user) {
|
||||
return $this->error(__("The user can't find it"));
|
||||
}
|
||||
return $this->success('', ['user' => $user]);
|
||||
}
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\admin\controller\user;
|
||||
|
||||
use Throwable;
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\model\User as UserModel;
|
||||
use Webman\Http\Request;
|
||||
use support\Response;
|
||||
|
||||
class User extends Backend
|
||||
{
|
||||
protected ?object $model = null;
|
||||
|
||||
protected array $withJoinTable = ['userGroup'];
|
||||
protected array|string $preExcludeFields = ['last_login_time', 'login_failure', 'password', 'salt'];
|
||||
protected array|string $quickSearchField = ['username', 'nickname', 'id'];
|
||||
|
||||
protected function initController(Request $request): ?Response
|
||||
{
|
||||
$this->model = new UserModel();
|
||||
return null;
|
||||
}
|
||||
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
$response = $this->initializeBackend($request);
|
||||
if ($response !== null) return $response;
|
||||
|
||||
if ($request->get('select') || $request->post('select')) {
|
||||
return $this->select($request);
|
||||
}
|
||||
|
||||
list($where, $alias, $limit, $order) = $this->queryBuilder();
|
||||
$res = $this->model
|
||||
->withoutField('password,salt')
|
||||
->withJoin($this->withJoinTable, $this->withJoinType)
|
||||
->alias($alias)
|
||||
->where($where)
|
||||
->order($order)
|
||||
->paginate($limit);
|
||||
|
||||
return $this->success('', [
|
||||
'list' => $res->items(),
|
||||
'total' => $res->total(),
|
||||
'remark' => get_route_remark(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function add(Request $request): Response
|
||||
{
|
||||
$response = $this->initializeBackend($request);
|
||||
if ($response !== null) return $response;
|
||||
|
||||
if ($request->method() !== 'POST') {
|
||||
return $this->error(__('Parameter error'));
|
||||
}
|
||||
|
||||
$data = $request->post();
|
||||
if (!$data) {
|
||||
return $this->error(__('Parameter %s can not be empty', ['']));
|
||||
}
|
||||
|
||||
$passwd = $data['password'] ?? '';
|
||||
$data = $this->excludeFields($data);
|
||||
|
||||
$result = false;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
if ($this->modelValidate) {
|
||||
$validateClass = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
if (class_exists($validateClass)) {
|
||||
$validate = new $validateClass();
|
||||
if ($this->modelSceneValidate) $validate->scene('add');
|
||||
$validate->check($data);
|
||||
}
|
||||
}
|
||||
$result = $this->model->save($data);
|
||||
$this->model->commit();
|
||||
if ($passwd) {
|
||||
$this->model->resetPassword($this->model->id, $passwd);
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
return $this->error($e->getMessage());
|
||||
}
|
||||
return $result !== false ? $this->success(__('Added successfully')) : $this->error(__('No rows were added'));
|
||||
}
|
||||
|
||||
public function edit(Request $request): Response
|
||||
{
|
||||
$response = $this->initializeBackend($request);
|
||||
if ($response !== null) return $response;
|
||||
|
||||
$pk = $this->model->getPk();
|
||||
$id = $request->post($pk) ?? $request->get($pk);
|
||||
$row = $this->model->find($id);
|
||||
if (!$row) {
|
||||
return $this->error(__('Record not found'));
|
||||
}
|
||||
|
||||
$dataLimitAdminIds = $this->getDataLimitAdminIds();
|
||||
if ($dataLimitAdminIds && !in_array($row[$this->dataLimitField], $dataLimitAdminIds)) {
|
||||
return $this->error(__('You have no permission'));
|
||||
}
|
||||
|
||||
if ($request->method() === 'POST') {
|
||||
$data = $request->post();
|
||||
if (!$data) {
|
||||
return $this->error(__('Parameter %s can not be empty', ['']));
|
||||
}
|
||||
if (!empty($data['password'])) {
|
||||
$this->model->resetPassword($row->id, $data['password']);
|
||||
}
|
||||
$data = $this->excludeFields($data);
|
||||
$result = false;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
if ($this->modelValidate) {
|
||||
$validateClass = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
if (class_exists($validateClass)) {
|
||||
$validate = new $validateClass();
|
||||
$validate->scene('edit')->check(array_merge($data, [$pk => $row[$pk]]));
|
||||
}
|
||||
}
|
||||
$result = $row->save($data);
|
||||
$this->model->commit();
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
return $this->error($e->getMessage());
|
||||
}
|
||||
return $result !== false ? $this->success(__('Update successful')) : $this->error(__('No rows updated'));
|
||||
}
|
||||
|
||||
unset($row['password'], $row['salt']);
|
||||
$row['password'] = '';
|
||||
return $this->success('', ['row' => $row]);
|
||||
}
|
||||
|
||||
public function select(Request $request): Response
|
||||
{
|
||||
$response = $this->initializeBackend($request);
|
||||
if ($response !== null) return $response;
|
||||
|
||||
list($where, $alias, $limit, $order) = $this->queryBuilder();
|
||||
$res = $this->model
|
||||
->withoutField('password,salt')
|
||||
->withJoin($this->withJoinTable, $this->withJoinType)
|
||||
->alias($alias)
|
||||
->where($where)
|
||||
->order($order)
|
||||
->paginate($limit);
|
||||
|
||||
return $this->success('', [
|
||||
'list' => $res->items(),
|
||||
'total' => $res->total(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use app\common\model\traits\TimestampInteger;
|
||||
use support\think\Model;
|
||||
use think\model\relation\BelongsTo;
|
||||
|
||||
class User extends Model
|
||||
{
|
||||
use TimestampInteger;
|
||||
|
||||
protected string $table = 'user';
|
||||
protected string $pk = 'id';
|
||||
protected bool $autoWriteTimestamp = true;
|
||||
|
||||
public function getAvatarAttr($value): string
|
||||
{
|
||||
return full_url($value ?? '', false, config('buildadmin.default_avatar'));
|
||||
}
|
||||
|
||||
public function setAvatarAttr($value): string
|
||||
{
|
||||
return $value === full_url('', false, config('buildadmin.default_avatar')) ? '' : $value;
|
||||
}
|
||||
|
||||
public function getMoneyAttr($value): string
|
||||
{
|
||||
return bcdiv((string) $value, '100', 2);
|
||||
}
|
||||
|
||||
public function setMoneyAttr($value): string
|
||||
{
|
||||
return bcmul((string) $value, '100', 2);
|
||||
}
|
||||
|
||||
public function userGroup(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(UserGroup::class, 'group_id');
|
||||
}
|
||||
|
||||
public function resetPassword(int|string $uid, string $newPassword): int
|
||||
{
|
||||
return $this->where(['id' => $uid])->update(['password' => hash_password($newPassword), 'salt' => '']);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use app\common\model\traits\TimestampInteger;
|
||||
use support\think\Model;
|
||||
|
||||
class UserGroup extends Model
|
||||
{
|
||||
use TimestampInteger;
|
||||
|
||||
protected string $table = 'user_group';
|
||||
protected string $pk = 'id';
|
||||
protected bool $autoWriteTimestamp = true;
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use app\common\model\traits\TimestampInteger;
|
||||
use support\think\Model;
|
||||
use think\model\relation\BelongsTo;
|
||||
|
||||
class UserMoneyLog extends Model
|
||||
{
|
||||
use TimestampInteger;
|
||||
|
||||
protected string $table = 'user_money_log';
|
||||
protected string $pk = 'id';
|
||||
protected bool $autoWriteTimestamp = true;
|
||||
protected bool $updateTime = false;
|
||||
|
||||
public static function onBeforeInsert($model): void
|
||||
{
|
||||
$user = User::where('id', $model->user_id)->lock(true)->find();
|
||||
if (!$user) {
|
||||
throw new \Exception(__("The user can't find it"));
|
||||
}
|
||||
if (!$model->memo) {
|
||||
throw new \Exception(__("Change note cannot be blank"));
|
||||
}
|
||||
$model->before = $user->money;
|
||||
$user->money += $model->money;
|
||||
$user->save();
|
||||
$model->after = $user->money;
|
||||
}
|
||||
|
||||
public static function onBeforeDelete(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getMoneyAttr($value): string
|
||||
{
|
||||
return bcdiv((string) $value, '100', 2);
|
||||
}
|
||||
|
||||
public function setMoneyAttr($value): string
|
||||
{
|
||||
return bcmul((string) $value, '100', 2);
|
||||
}
|
||||
|
||||
public function getBeforeAttr($value): string
|
||||
{
|
||||
return bcdiv((string) $value, '100', 2);
|
||||
}
|
||||
|
||||
public function setBeforeAttr($value): string
|
||||
{
|
||||
return bcmul((string) $value, '100', 2);
|
||||
}
|
||||
|
||||
public function getAfterAttr($value): string
|
||||
{
|
||||
return bcdiv((string) $value, '100', 2);
|
||||
}
|
||||
|
||||
public function setAfterAttr($value): string
|
||||
{
|
||||
return bcmul((string) $value, '100', 2);
|
||||
}
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id');
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use app\common\model\traits\TimestampInteger;
|
||||
use support\think\Model;
|
||||
use think\model\relation\BelongsTo;
|
||||
|
||||
class UserScoreLog extends Model
|
||||
{
|
||||
use TimestampInteger;
|
||||
|
||||
protected string $table = 'user_score_log';
|
||||
protected string $pk = 'id';
|
||||
protected bool $autoWriteTimestamp = true;
|
||||
protected bool $updateTime = false;
|
||||
|
||||
public static function onBeforeInsert($model): void
|
||||
{
|
||||
$user = User::where('id', $model->user_id)->lock(true)->find();
|
||||
if (!$user) {
|
||||
throw new \Exception(__("The user can't find it"));
|
||||
}
|
||||
if (!$model->memo) {
|
||||
throw new \Exception(__("Change note cannot be blank"));
|
||||
}
|
||||
$model->before = $user->score;
|
||||
$user->score += $model->score;
|
||||
$user->save();
|
||||
$model->after = $user->score;
|
||||
}
|
||||
|
||||
public static function onBeforeDelete(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id');
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\admin\validate;
|
||||
|
||||
use think\Validate;
|
||||
|
||||
class UserMoneyLog extends Validate
|
||||
{
|
||||
protected $failException = true;
|
||||
|
||||
protected $rule = [
|
||||
'user_id' => 'require',
|
||||
'money' => 'require',
|
||||
'memo' => 'require',
|
||||
];
|
||||
|
||||
protected $message = [];
|
||||
|
||||
protected $field = [];
|
||||
|
||||
protected $scene = [
|
||||
'add' => ['user_id', 'money', 'memo'],
|
||||
'edit' => ['user_id', 'money', 'memo'],
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->field = [
|
||||
'user_id' => __('user_id'),
|
||||
'money' => __('money'),
|
||||
'memo' => __('memo'),
|
||||
];
|
||||
parent::__construct();
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\admin\validate;
|
||||
|
||||
use think\Validate;
|
||||
|
||||
class UserScoreLog extends Validate
|
||||
{
|
||||
protected $failException = true;
|
||||
|
||||
protected $rule = [
|
||||
'user_id' => 'require',
|
||||
'score' => 'require',
|
||||
'memo' => 'require',
|
||||
];
|
||||
|
||||
protected $message = [];
|
||||
|
||||
protected $field = [];
|
||||
|
||||
protected $scene = [
|
||||
'add' => ['user_id', 'score', 'memo'],
|
||||
'edit' => ['user_id', 'score', 'memo'],
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->field = [
|
||||
'user_id' => __('user_id'),
|
||||
'score' => __('score'),
|
||||
'memo' => __('memo'),
|
||||
];
|
||||
parent::__construct();
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,6 @@ use ba\Terminal;
|
||||
use ba\Filesystem;
|
||||
use app\common\controller\Api;
|
||||
use app\admin\model\Admin as AdminModel;
|
||||
use app\admin\model\User as UserModel;
|
||||
use app\process\Monitor;
|
||||
use support\Response;
|
||||
use Webman\Http\Request;
|
||||
@@ -627,10 +626,6 @@ class Install extends Api
|
||||
$adminModel->resetPassword($defaultAdmin->id, $param['adminpassword']);
|
||||
}
|
||||
|
||||
// 默认用户密码修改
|
||||
$user = new UserModel();
|
||||
$user->resetPassword(1, Random::build());
|
||||
|
||||
// 修改站点名称
|
||||
if (class_exists(\app\admin\model\Config::class)) {
|
||||
\app\admin\model\Config::where('name', 'site_name')->update([
|
||||
|
||||
@@ -6,6 +6,7 @@ use ba\Captcha;
|
||||
use ba\ClickCaptcha;
|
||||
use app\common\controller\Frontend;
|
||||
use app\common\facade\Token;
|
||||
use support\think\Db;
|
||||
use support\validation\Validator;
|
||||
use support\validation\ValidationException;
|
||||
use Webman\Http\Request;
|
||||
@@ -46,6 +47,7 @@ class User extends Frontend
|
||||
'captchaId' => $params['captchaId'] ?? '',
|
||||
'captchaInfo' => $params['captchaInfo'] ?? '',
|
||||
'registerType' => $params['registerType'] ?? '',
|
||||
'invite_code' => $params['invite_code'] ?? '',
|
||||
]);
|
||||
|
||||
if (!in_array($params['tab'], ['login', 'register'])) {
|
||||
@@ -72,7 +74,20 @@ class User extends Frontend
|
||||
if (!$captchaObj->check($params['captcha'], $params[$params['registerType']] . 'user_register')) {
|
||||
return $this->error(__('Please enter the correct verification code'));
|
||||
}
|
||||
$res = $this->auth->register($params['username'], $params['password'], $params['mobile'], $params['email']);
|
||||
$extend = [];
|
||||
if (!empty($params['invite_code'])) {
|
||||
$inviterAdmin = Db::name('admin')
|
||||
->field(['id', 'channel_id'])
|
||||
->where('invite_code', $params['invite_code'])
|
||||
->find();
|
||||
if (!$inviterAdmin) {
|
||||
return $this->error(__('Parameter error'));
|
||||
}
|
||||
$extend['register_invite_code'] = $params['invite_code'];
|
||||
$extend['inviter_admin_id'] = $inviterAdmin['id'];
|
||||
$extend['channel_id'] = $inviterAdmin['channel_id'] ?? null;
|
||||
}
|
||||
$res = $this->auth->register($params['username'], $params['password'], $params['mobile'], $params['email'], 1, $extend);
|
||||
}
|
||||
|
||||
if ($res === true) {
|
||||
@@ -117,6 +132,7 @@ class User extends Frontend
|
||||
'email' => 'required_if:registerType,email|email|unique:user,email',
|
||||
'mobile' => 'required_if:registerType,mobile|regex:/^1[3-9]\d{9}$/|unique:user,mobile',
|
||||
'captcha' => 'required|string',
|
||||
'invite_code' => 'nullable|string|max:64',
|
||||
],
|
||||
[
|
||||
'username.regex' => __('Please input correct username'),
|
||||
@@ -129,6 +145,7 @@ class User extends Frontend
|
||||
'password' => __('Password'),
|
||||
'captcha' => __('captcha'),
|
||||
'registerType' => __('Register type'),
|
||||
'invite_code' => __('Invite code'),
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ if (!function_exists('get_controller_path')) {
|
||||
* 从 Request 或路由获取控制器路径(等价于 ThinkPHP controllerPath)
|
||||
* 优先从 $request->controller(Webman 路由匹配时设置)解析,否则从 path 解析
|
||||
* @param \Webman\Http\Request|null $request
|
||||
* @return string|null 如 auth/admin、user/user
|
||||
* @return string|null 如 auth/admin
|
||||
*/
|
||||
function get_controller_path($request = null): ?string
|
||||
{
|
||||
|
||||
@@ -172,29 +172,6 @@ Route::get('/admin/auth/rule/select', [\app\admin\controller\auth\Rule::class, '
|
||||
// admin/auth/adminLog
|
||||
Route::get('/admin/auth/adminLog/index', [\app\admin\controller\auth\AdminLog::class, 'index']);
|
||||
|
||||
// admin/user/user
|
||||
Route::get('/admin/user/user/index', [\app\admin\controller\user\User::class, 'index']);
|
||||
Route::post('/admin/user/user/add', [\app\admin\controller\user\User::class, 'add']);
|
||||
Route::post('/admin/user/user/edit', [\app\admin\controller\user\User::class, 'edit']);
|
||||
Route::get('/admin/user/user/select', [\app\admin\controller\user\User::class, 'select']);
|
||||
|
||||
// admin/user/group
|
||||
Route::post('/admin/user/group/add', [\app\admin\controller\user\Group::class, 'add']);
|
||||
Route::post('/admin/user/group/edit', [\app\admin\controller\user\Group::class, 'edit']);
|
||||
|
||||
// admin/user/rule
|
||||
Route::get('/admin/user/rule/index', [\app\admin\controller\user\Rule::class, 'index']);
|
||||
Route::post('/admin/user/rule/add', [\app\admin\controller\user\Rule::class, 'add']);
|
||||
Route::post('/admin/user/rule/edit', [\app\admin\controller\user\Rule::class, 'edit']);
|
||||
Route::post('/admin/user/rule/del', [\app\admin\controller\user\Rule::class, 'del']);
|
||||
Route::get('/admin/user/rule/select', [\app\admin\controller\user\Rule::class, 'select']);
|
||||
|
||||
// admin/user/scoreLog
|
||||
Route::post('/admin/user/scoreLog/add', [\app\admin\controller\user\ScoreLog::class, 'add']);
|
||||
|
||||
// admin/user/moneyLog
|
||||
Route::post('/admin/user/moneyLog/add', [\app\admin\controller\user\MoneyLog::class, 'add']);
|
||||
|
||||
// admin/routine/config
|
||||
Route::get('/admin/routine/config/index', [\app\admin\controller\routine\Config::class, 'index']);
|
||||
Route::post('/admin/routine/config/edit', [\app\admin\controller\routine\Config::class, 'edit']);
|
||||
|
||||
@@ -17,8 +17,6 @@ class InstallData extends AbstractMigration
|
||||
$this->menuRule();
|
||||
$this->securityDataRecycle();
|
||||
$this->securitySensitiveData();
|
||||
$this->user();
|
||||
$this->userGroup();
|
||||
$this->userRule();
|
||||
}
|
||||
|
||||
@@ -456,245 +454,6 @@ class InstallData extends AbstractMigration
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => '21',
|
||||
'type' => 'menu_dir',
|
||||
'title' => '会员管理',
|
||||
'name' => 'user',
|
||||
'path' => 'user',
|
||||
'icon' => 'fa fa-drivers-license',
|
||||
'weigh' => '95',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => '22',
|
||||
'pid' => '21',
|
||||
'type' => 'menu',
|
||||
'title' => '会员管理',
|
||||
'name' => 'user/user',
|
||||
'path' => 'user/user',
|
||||
'icon' => 'fa fa-user',
|
||||
'menu_type' => 'tab',
|
||||
'component' => '/src/views/backend/user/user/index.vue',
|
||||
'keepalive' => '1',
|
||||
'weigh' => '94',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => '23',
|
||||
'pid' => '22',
|
||||
'type' => 'button',
|
||||
'title' => '查看',
|
||||
'name' => 'user/user/index',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => '24',
|
||||
'pid' => '22',
|
||||
'type' => 'button',
|
||||
'title' => '添加',
|
||||
'name' => 'user/user/add',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => '25',
|
||||
'pid' => '22',
|
||||
'type' => 'button',
|
||||
'title' => '编辑',
|
||||
'name' => 'user/user/edit',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => '26',
|
||||
'pid' => '22',
|
||||
'type' => 'button',
|
||||
'title' => '删除',
|
||||
'name' => 'user/user/del',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => '27',
|
||||
'pid' => '21',
|
||||
'type' => 'menu',
|
||||
'title' => '会员分组管理',
|
||||
'name' => 'user/group',
|
||||
'path' => 'user/group',
|
||||
'icon' => 'fa fa-group',
|
||||
'menu_type' => 'tab',
|
||||
'component' => '/src/views/backend/user/group/index.vue',
|
||||
'keepalive' => '1',
|
||||
'weigh' => '93',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => '28',
|
||||
'pid' => '27',
|
||||
'type' => 'button',
|
||||
'title' => '查看',
|
||||
'name' => 'user/group/index',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => '29',
|
||||
'pid' => '27',
|
||||
'type' => 'button',
|
||||
'title' => '添加',
|
||||
'name' => 'user/group/add',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => '30',
|
||||
'pid' => '27',
|
||||
'type' => 'button',
|
||||
'title' => '编辑',
|
||||
'name' => 'user/group/edit',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => '31',
|
||||
'pid' => '27',
|
||||
'type' => 'button',
|
||||
'title' => '删除',
|
||||
'name' => 'user/group/del',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => '32',
|
||||
'pid' => '21',
|
||||
'type' => 'menu',
|
||||
'title' => '会员规则管理',
|
||||
'name' => 'user/rule',
|
||||
'path' => 'user/rule',
|
||||
'icon' => 'fa fa-th-list',
|
||||
'menu_type' => 'tab',
|
||||
'component' => '/src/views/backend/user/rule/index.vue',
|
||||
'keepalive' => '1',
|
||||
'weigh' => '92',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => '33',
|
||||
'pid' => '32',
|
||||
'type' => 'button',
|
||||
'title' => '查看',
|
||||
'name' => 'user/rule/index',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => '34',
|
||||
'pid' => '32',
|
||||
'type' => 'button',
|
||||
'title' => '添加',
|
||||
'name' => 'user/rule/add',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => '35',
|
||||
'pid' => '32',
|
||||
'type' => 'button',
|
||||
'title' => '编辑',
|
||||
'name' => 'user/rule/edit',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => '36',
|
||||
'pid' => '32',
|
||||
'type' => 'button',
|
||||
'title' => '删除',
|
||||
'name' => 'user/rule/del',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => '37',
|
||||
'pid' => '32',
|
||||
'type' => 'button',
|
||||
'title' => '快速排序',
|
||||
'name' => 'user/rule/sortable',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => '38',
|
||||
'pid' => '21',
|
||||
'type' => 'menu',
|
||||
'title' => '会员余额管理',
|
||||
'name' => 'user/moneyLog',
|
||||
'path' => 'user/moneyLog',
|
||||
'icon' => 'el-icon-Money',
|
||||
'menu_type' => 'tab',
|
||||
'component' => '/src/views/backend/user/moneyLog/index.vue',
|
||||
'keepalive' => '1',
|
||||
'weigh' => '91',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => '39',
|
||||
'pid' => '38',
|
||||
'type' => 'button',
|
||||
'title' => '查看',
|
||||
'name' => 'user/moneyLog/index',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => '40',
|
||||
'pid' => '38',
|
||||
'type' => 'button',
|
||||
'title' => '添加',
|
||||
'name' => 'user/moneyLog/add',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => '41',
|
||||
'pid' => '21',
|
||||
'type' => 'menu',
|
||||
'title' => '会员积分管理',
|
||||
'name' => 'user/scoreLog',
|
||||
'path' => 'user/scoreLog',
|
||||
'icon' => 'el-icon-Discount',
|
||||
'menu_type' => 'tab',
|
||||
'component' => '/src/views/backend/user/scoreLog/index.vue',
|
||||
'keepalive' => '1',
|
||||
'weigh' => '90',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => '42',
|
||||
'pid' => '41',
|
||||
'type' => 'button',
|
||||
'title' => '查看',
|
||||
'name' => 'user/scoreLog/index',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => '43',
|
||||
'pid' => '41',
|
||||
'type' => 'button',
|
||||
'title' => '添加',
|
||||
'name' => 'user/scoreLog/add',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => '44',
|
||||
'type' => 'menu_dir',
|
||||
@@ -1214,16 +973,6 @@ class InstallData extends AbstractMigration
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => 5,
|
||||
'name' => '会员',
|
||||
'controller' => 'user/User.php',
|
||||
'controller_as' => 'user/user',
|
||||
'data_table' => 'user',
|
||||
'primary_key' => 'id',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => 6,
|
||||
'name' => '数据回收规则',
|
||||
@@ -1257,18 +1006,6 @@ class InstallData extends AbstractMigration
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => 2,
|
||||
'name' => '会员数据',
|
||||
'controller' => 'user/User.php',
|
||||
'controller_as' => 'user/user',
|
||||
'data_table' => 'user',
|
||||
'primary_key' => 'id',
|
||||
'data_fields' => '{"username":"用户名","mobile":"手机号","password":"密码","status":"状态","email":"邮箱地址"}',
|
||||
'status' => '1',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
],
|
||||
[
|
||||
'id' => 3,
|
||||
'name' => '管理员权限',
|
||||
@@ -1288,49 +1025,6 @@ class InstallData extends AbstractMigration
|
||||
}
|
||||
}
|
||||
|
||||
public function user(): void
|
||||
{
|
||||
$table = $this->table('user');
|
||||
$rows = [
|
||||
[
|
||||
'id' => 1,
|
||||
'group_id' => 1,
|
||||
'username' => 'user',
|
||||
'nickname' => 'User',
|
||||
'email' => '18888888888@qq.com',
|
||||
'mobile' => '18888888888',
|
||||
'gender' => '2',
|
||||
'birthday' => date('Y-m-d'),
|
||||
'status' => 'enable',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
]
|
||||
];
|
||||
$exist = Db::name('user')->where('id', 1)->value('id');
|
||||
if (!$exist) {
|
||||
$table->insert($rows)->saveData();
|
||||
}
|
||||
}
|
||||
|
||||
public function userGroup(): void
|
||||
{
|
||||
$table = $this->table('user_group');
|
||||
$rows = [
|
||||
[
|
||||
'id' => 1,
|
||||
'name' => '默认分组',
|
||||
'rules' => '*',
|
||||
'status' => '1',
|
||||
'updatetime' => $this->nowTime,
|
||||
'createtime' => $this->nowTime,
|
||||
]
|
||||
];
|
||||
$exist = Db::name('user_group')->where('id', 1)->value('id');
|
||||
if (!$exist) {
|
||||
$table->insert($rows)->saveData();
|
||||
}
|
||||
}
|
||||
|
||||
public function userRule(): void
|
||||
{
|
||||
$table = $this->table('user_rule');
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
import createAxios from '/@/utils/axios'
|
||||
|
||||
export function getUserRules() {
|
||||
return createAxios({
|
||||
url: '/admin/user.Rule/index',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import createAxios from '/@/utils/axios'
|
||||
|
||||
export const url = '/admin/user.MoneyLog/'
|
||||
|
||||
export function add(userId: string) {
|
||||
return createAxios({
|
||||
url: url + 'add',
|
||||
method: 'get',
|
||||
params: {
|
||||
userId: userId,
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import createAxios from '/@/utils/axios'
|
||||
|
||||
export const url = '/admin/user.ScoreLog/'
|
||||
|
||||
export function add(userId: string) {
|
||||
return createAxios({
|
||||
url: url + 'add',
|
||||
method: 'get',
|
||||
params: {
|
||||
userId: userId,
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -8,7 +8,5 @@ import { adminBaseRoutePath } from '/@/router/static/adminBase'
|
||||
export default {
|
||||
'/': ['./frontend/${lang}/index.ts'],
|
||||
[adminBaseRoutePath + '/moduleStore']: ['./backend/${lang}/module.ts'],
|
||||
[adminBaseRoutePath + '/user/rule']: ['./backend/${lang}/auth/rule.ts'],
|
||||
[adminBaseRoutePath + '/user/scoreLog']: ['./backend/${lang}/user/moneyLog.ts'],
|
||||
[adminBaseRoutePath + '/crud/crud']: ['./backend/${lang}/crud/log.ts', './backend/${lang}/crud/state.ts'],
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
export default {
|
||||
GroupName: 'Group name',
|
||||
'Group name': 'Group name',
|
||||
jurisdiction: 'Permissions',
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
export default {
|
||||
'User name': 'Username',
|
||||
'User nickname': 'User nickname',
|
||||
balance: 'Balance',
|
||||
'User ID': 'User ID',
|
||||
'Change balance': 'Change balance',
|
||||
'Before change': 'Before the change',
|
||||
'After change': 'After the change',
|
||||
remarks: 'Remark',
|
||||
'Current balance': 'Current balance',
|
||||
'Change amount': 'Change amount',
|
||||
'Please enter the balance change amount': 'Please enter the balance change amount.',
|
||||
'Balance after change': 'Balance after change',
|
||||
'Please enter change remarks / description': 'Please enter change remarks/description',
|
||||
User: 'User',
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
export default {
|
||||
'Normal routing': 'Normal routing',
|
||||
'Member center menu contents': 'Member center menu directory ',
|
||||
'Member center menu items': 'Member Center menu items',
|
||||
'Top bar menu items': 'Top bar menu items',
|
||||
'Page button': 'Page button',
|
||||
'Top bar user dropdown': 'Top bar user dropdown',
|
||||
'Type route tips': 'Automatically register as a front-end route',
|
||||
'Type menu_dir tips': 'Automatically register routes and serve as menu directory of member center This item cannot jump',
|
||||
'Type menu tips': 'Automatically register routes and serve as menu items in member centers',
|
||||
'Type nav tips': 'Routes are automatically registered as menu items in the top bar of the site',
|
||||
'Type button tips': 'Automatic registration as a permission node, can be quickly verified by v-auth',
|
||||
'Type nav_user_menu tips': 'Automatically register routes and serve as a dropdown menu for top bar members',
|
||||
'English name': 'English name',
|
||||
'Web side routing path': 'Web side routing path',
|
||||
no_login_valid: 'no login valid',
|
||||
'no_login_valid 0': 'no',
|
||||
'no_login_valid 1': 'yes',
|
||||
'no_login_valid tips': 'Tourists do not have membership groups Use this option to set whether the current rules are valid for tourists (visible)',
|
||||
'For example, if you add account/overview as a route only':
|
||||
'Please start with /src for web side component paths, such as: /src/views/frontend/index.vue',
|
||||
'Web side component path, please start with /src, such as: /src/views/frontend/index':
|
||||
"For example, if you add 'account/overview' as a route only, then you can additionally add 'account/overview', 'account/overview/:a' and 'account/overview/:b/:C' as menus only.",
|
||||
'Component path tips':
|
||||
'This item is mandatory within a WEB project; otherwise, it cannot be accessed. However, when it is used as a menu within a Nuxt project, there is no need to fill in this item',
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
export default {
|
||||
integral: 'Integral',
|
||||
'Change points': 'Change points',
|
||||
'Current points': 'Current points',
|
||||
'Please enter the change amount of points': 'Please enter the change amount of points',
|
||||
'Points after change': 'Points after change',
|
||||
'Please enter change remarks / description': 'Please enter change remarks/description',
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
export default {
|
||||
'User name': 'Username',
|
||||
nickname: 'Nickname',
|
||||
group: 'Group',
|
||||
avatar: 'Avatar',
|
||||
Gender: 'Gender',
|
||||
male: 'Male',
|
||||
female: 'Female',
|
||||
mobile: 'Mobile Number',
|
||||
'Last login IP': 'Last login IP',
|
||||
'Last login': 'Last login',
|
||||
email: 'Email',
|
||||
birthday: 'Birthday',
|
||||
balance: 'Balance',
|
||||
'Adjustment balance': 'Adjust balance',
|
||||
integral: 'Integral',
|
||||
'Adjust integral': 'Adjust integral',
|
||||
password: 'Password',
|
||||
'Please leave blank if not modified': 'Please leave blank if you do not modify',
|
||||
'Personal signature': 'Personal signature',
|
||||
'Login account': 'Login account name',
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
export default {
|
||||
GroupName: '组名',
|
||||
'Group name': '组别名称',
|
||||
jurisdiction: '权限',
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
export default {
|
||||
'User name': '用户名',
|
||||
'User nickname': '用户昵称',
|
||||
balance: '余额',
|
||||
'User ID': '用户ID',
|
||||
'Change balance': '变更余额',
|
||||
'Before change': '变更前',
|
||||
'After change': '变更后',
|
||||
remarks: '备注',
|
||||
'Current balance': '当前余额',
|
||||
'Change amount': '变动数额',
|
||||
'Please enter the balance change amount': '请输入余额变更数额',
|
||||
'Balance after change': '变更后余额',
|
||||
'Please enter change remarks / description': '请输入变更备注/说明',
|
||||
User: '用户',
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
export default {
|
||||
'Normal routing': '普通路由',
|
||||
'Member center menu contents': '会员中心菜单目录',
|
||||
'Member center menu items': '会员中心菜单项',
|
||||
'Top bar menu items': '顶栏菜单项',
|
||||
'Page button': '页面按钮',
|
||||
'Top bar user dropdown': '顶栏会员菜单下拉项',
|
||||
'Type route tips': '自动注册为前端路由',
|
||||
'Type menu_dir tips': '自动注册路由,并作为会员中心的菜单目录,此项本身不可跳转',
|
||||
'Type menu tips': '自动注册路由,并作为会员中心的菜单项目',
|
||||
'Type nav tips': '自动注册路由,并作为站点顶栏的菜单项目',
|
||||
'Type button tips': '自动注册为权限节点,可通过 v-auth 快速验权',
|
||||
'Type nav_user_menu tips': '自动注册路由,并作为顶栏会员菜单下拉项',
|
||||
'English name': '英文名称',
|
||||
'Web side routing path': 'WEB 端路由路径(vue-router 的 path)',
|
||||
no_login_valid: '未登录有效',
|
||||
'no_login_valid 0': '游客无效',
|
||||
'no_login_valid 1': '游客有效',
|
||||
'no_login_valid tips': '游客没有会员分组,通过本选项设置当前规则是否对游客有效(可见)',
|
||||
'For example, if you add account/overview as a route only': 'WEB 端组件路径,请以 /src 开头,如:/src/views/frontend/index.vue',
|
||||
'Web side component path, please start with /src, such as: /src/views/frontend/index':
|
||||
'比如将 `account/overview` 只添加为路由,那么可以另外将 `account/overview`、`account/overview/:a`、`account/overview/:b/:c` 只添加为菜单',
|
||||
'Component path tips': '组件路径在 WEB 工程内是必填的,否则无法访问,但作为 Nuxt 工程内的菜单时,无需填写此项,请根据菜单使用场景填写',
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
export default {
|
||||
integral: '积分',
|
||||
'Change points': '变更积分',
|
||||
'Current points': '当前积分',
|
||||
'Please enter the change amount of points': '请输入积分变更数额',
|
||||
'Points after change': '变更后积分',
|
||||
'Please enter change remarks / description': '请输入变更备注/说明',
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
export default {
|
||||
'User name': '用户名',
|
||||
nickname: '昵称',
|
||||
group: '分组',
|
||||
avatar: '头像',
|
||||
Gender: '性别',
|
||||
male: '男',
|
||||
female: '女',
|
||||
mobile: '手机号',
|
||||
'Last login IP': '最后登录IP',
|
||||
'Last login': '最后登录',
|
||||
email: '电子邮箱',
|
||||
birthday: '生日',
|
||||
balance: '余额',
|
||||
'Adjustment balance': '调整余额',
|
||||
integral: '积分',
|
||||
'Adjust integral': '调整积分',
|
||||
password: '密码',
|
||||
'Please leave blank if not modified': '不修改请留空',
|
||||
'Personal signature': '个性签名',
|
||||
'Login account': '登录账户名',
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
<template>
|
||||
<div class="default-main ba-table-box">
|
||||
<el-alert class="ba-table-alert" v-if="baTable.table.remark" :title="baTable.table.remark" type="info" show-icon />
|
||||
|
||||
<!-- 表格顶部菜单 -->
|
||||
<TableHeader
|
||||
:buttons="['refresh', 'add', 'edit', 'delete', 'comSearch', 'quickSearch', 'columnDisplay']"
|
||||
:quick-search-placeholder="t('Quick search placeholder', { fields: t('user.group.GroupName') })"
|
||||
/>
|
||||
|
||||
<!-- 表格 -->
|
||||
<!-- 要使用`el-table`组件原有的属性,直接加在Table标签上即可 -->
|
||||
<Table ref="tableRef" />
|
||||
|
||||
<!-- 表单 -->
|
||||
<PopupForm ref="formRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, provide, useTemplateRef } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import PopupForm from './popupForm.vue'
|
||||
import { getUserRules } from '/@/api/backend/user/group'
|
||||
import { baTableApi } from '/@/api/common'
|
||||
import { defaultOptButtons } from '/@/components/table'
|
||||
import TableHeader from '/@/components/table/header/index.vue'
|
||||
import Table from '/@/components/table/index.vue'
|
||||
import baTableClass from '/@/utils/baTable'
|
||||
import { uuid } from '/@/utils/random'
|
||||
|
||||
defineOptions({
|
||||
name: 'user/group',
|
||||
})
|
||||
|
||||
const { t } = useI18n()
|
||||
const formRef = useTemplateRef('formRef')
|
||||
const tableRef = useTemplateRef('tableRef')
|
||||
|
||||
const baTable = new baTableClass(
|
||||
new baTableApi('/admin/user.Group/'),
|
||||
{
|
||||
column: [
|
||||
{ type: 'selection', align: 'center', operator: false },
|
||||
{ label: t('Id'), prop: 'id', align: 'center', operator: '=', operatorPlaceholder: t('Id'), width: 70 },
|
||||
{ label: t('user.group.Group name'), prop: 'name', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') },
|
||||
{
|
||||
label: t('State'),
|
||||
prop: 'status',
|
||||
align: 'center',
|
||||
render: 'tag',
|
||||
custom: { 0: 'danger', 1: 'success' },
|
||||
replaceValue: { 0: t('Disable'), 1: t('Enable') },
|
||||
},
|
||||
{ label: t('Update time'), prop: 'update_time', align: 'center', render: 'datetime', sortable: 'custom', operator: 'RANGE', width: 160 },
|
||||
{ label: t('Create time'), prop: 'create_time', align: 'center', render: 'datetime', sortable: 'custom', operator: 'RANGE', width: 160 },
|
||||
{
|
||||
label: t('Operate'),
|
||||
align: 'center',
|
||||
width: '130',
|
||||
render: 'buttons',
|
||||
buttons: defaultOptButtons(['edit', 'delete']),
|
||||
operator: false,
|
||||
},
|
||||
],
|
||||
dblClickNotEditColumn: [undefined],
|
||||
},
|
||||
{
|
||||
defaultItems: {
|
||||
status: 1,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// 利用提交前钩子重写提交操作
|
||||
baTable.before.onSubmit = ({ formEl, operate, items }) => {
|
||||
let submitCallback = () => {
|
||||
baTable.form.submitLoading = true
|
||||
baTable.api
|
||||
.postData(operate, {
|
||||
...items,
|
||||
rules: formRef.value?.getCheckeds(),
|
||||
})
|
||||
.then((res) => {
|
||||
baTable.onTableHeaderAction('refresh', {})
|
||||
baTable.form.submitLoading = false
|
||||
baTable.form.operateIds?.shift()
|
||||
if (baTable.form.operateIds!.length > 0) {
|
||||
baTable.toggleForm('Edit', baTable.form.operateIds)
|
||||
} else {
|
||||
baTable.toggleForm()
|
||||
}
|
||||
baTable.runAfter('onSubmit', { res })
|
||||
})
|
||||
.catch(() => {
|
||||
baTable.form.submitLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
if (formEl) {
|
||||
baTable.form.ref = formEl
|
||||
formEl.validate((valid) => {
|
||||
if (valid) {
|
||||
submitCallback()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
submitCallback()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 打开表单后
|
||||
baTable.after.toggleForm = ({ operate }) => {
|
||||
if (operate == 'Add') {
|
||||
menuRuleTreeUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
// 获取到编辑数据后
|
||||
baTable.after.getEditData = () => {
|
||||
menuRuleTreeUpdate()
|
||||
}
|
||||
|
||||
const menuRuleTreeUpdate = () => {
|
||||
getUserRules().then((res) => {
|
||||
baTable.form.extend!.menuRules = res.data.list
|
||||
|
||||
if (baTable.form.items!.rules && baTable.form.items!.rules.length) {
|
||||
if (baTable.form.items!.rules.includes('*')) {
|
||||
let arr: number[] = []
|
||||
for (const key in baTable.form.extend!.menuRules) {
|
||||
arr.push(baTable.form.extend!.menuRules[key].id)
|
||||
}
|
||||
baTable.form.extend!.defaultCheckedKeys = arr
|
||||
} else {
|
||||
baTable.form.extend!.defaultCheckedKeys = baTable.form.items!.rules
|
||||
}
|
||||
} else {
|
||||
baTable.form.extend!.defaultCheckedKeys = []
|
||||
}
|
||||
baTable.form.extend!.treeKey = uuid()
|
||||
})
|
||||
}
|
||||
|
||||
provide('baTable', baTable)
|
||||
|
||||
onMounted(() => {
|
||||
baTable.table.ref = tableRef.value
|
||||
baTable.mount()
|
||||
baTable.getData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -1,145 +0,0 @@
|
||||
<template>
|
||||
<!-- 对话框表单 -->
|
||||
<el-dialog
|
||||
class="ba-operate-dialog"
|
||||
top="10vh"
|
||||
:close-on-click-modal="false"
|
||||
:model-value="['Add', 'Edit'].includes(baTable.form.operate!)"
|
||||
@close="baTable.toggleForm"
|
||||
:destroy-on-close="true"
|
||||
>
|
||||
<template #header>
|
||||
<div class="title" v-drag="['.ba-operate-dialog', '.el-dialog__header']" v-zoom="'.ba-operate-dialog'">
|
||||
{{ baTable.form.operate ? t(baTable.form.operate) : '' }}
|
||||
</div>
|
||||
</template>
|
||||
<el-scrollbar v-loading="baTable.form.loading" class="ba-table-form-scrollbar">
|
||||
<div
|
||||
class="ba-operate-form"
|
||||
:class="'ba-' + baTable.form.operate + '-form'"
|
||||
:style="config.layout.shrink ? '' : 'width: calc(100% - ' + baTable.form.labelWidth! / 2 + 'px)'"
|
||||
>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
@submit.prevent=""
|
||||
@keyup.enter="baTable.onSubmit(formRef)"
|
||||
:model="baTable.form.items"
|
||||
:label-position="config.layout.shrink ? 'top' : 'right'"
|
||||
:label-width="baTable.form.labelWidth + 'px'"
|
||||
:rules="rules"
|
||||
>
|
||||
<el-form-item prop="name" :label="t('user.group.Group name')">
|
||||
<el-input
|
||||
v-model="baTable.form.items!.name"
|
||||
type="string"
|
||||
:placeholder="t('Please input field', { field: t('user.group.Group name') })"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="auth" :label="t('user.group.jurisdiction')">
|
||||
<el-tree
|
||||
ref="treeRef"
|
||||
:key="baTable.form.extend!.treeKey"
|
||||
:default-checked-keys="baTable.form.extend!.defaultCheckedKeys"
|
||||
:default-expand-all="true"
|
||||
show-checkbox
|
||||
node-key="id"
|
||||
:props="{ children: 'children', label: 'title', class: treeNodeClass }"
|
||||
:data="baTable.form.extend!.menuRules"
|
||||
class="w100"
|
||||
/>
|
||||
</el-form-item>
|
||||
<FormItem
|
||||
:label="t('State')"
|
||||
v-model="baTable.form.items!.status"
|
||||
type="radio"
|
||||
:input-attr="{
|
||||
border: true,
|
||||
content: { 0: t('Disable'), 1: t('Enable') },
|
||||
}"
|
||||
/>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
<template #footer>
|
||||
<div :style="'width: calc(100% - ' + baTable.form.labelWidth! / 1.8 + 'px)'">
|
||||
<el-button @click="baTable.toggleForm('')">{{ t('Cancel') }}</el-button>
|
||||
<el-button v-blur :loading="baTable.form.submitLoading" @click="baTable.onSubmit(formRef)" type="primary">
|
||||
{{ baTable.form.operateIds && baTable.form.operateIds.length > 1 ? t('Save and edit next item') : t('Save') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, inject, useTemplateRef } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import type baTableClass from '/@/utils/baTable'
|
||||
import type { ElTree, FormItemRule } from 'element-plus'
|
||||
import FormItem from '/@/components/formItem/index.vue'
|
||||
import type Node from 'element-plus/es/components/tree/src/model/node'
|
||||
import { buildValidatorData } from '/@/utils/validate'
|
||||
import { useConfig } from '/@/stores/config'
|
||||
|
||||
const config = useConfig()
|
||||
const formRef = useTemplateRef('formRef')
|
||||
const treeRef = useTemplateRef('treeRef')
|
||||
const baTable = inject('baTable') as baTableClass
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const rules: Partial<Record<string, FormItemRule[]>> = reactive({
|
||||
name: [buildValidatorData({ name: 'required', title: t('user.group.Group name') })],
|
||||
auth: [
|
||||
{
|
||||
required: true,
|
||||
validator: (rule: any, val: string, callback: Function) => {
|
||||
let ids = getCheckeds()
|
||||
if (ids.length <= 0) {
|
||||
return callback(new Error(t('Please select field', { field: t('user.group.jurisdiction') })))
|
||||
}
|
||||
return callback()
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const getCheckeds = () => {
|
||||
return treeRef.value!.getCheckedKeys().concat(treeRef.value!.getHalfCheckedKeys())
|
||||
}
|
||||
|
||||
const treeNodeClass = (data: anyObj, node: Node) => {
|
||||
if (node.isLeaf) return ''
|
||||
let addClass = true
|
||||
for (const key in node.childNodes) {
|
||||
if (!node.childNodes[key].isLeaf) {
|
||||
addClass = false
|
||||
}
|
||||
}
|
||||
return addClass ? 'penultimate-node' : ''
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
getCheckeds,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:deep(.penultimate-node) {
|
||||
.el-tree-node__children {
|
||||
padding-left: 60px;
|
||||
white-space: pre-wrap;
|
||||
line-height: 12px;
|
||||
.el-tree-node {
|
||||
display: inline-block;
|
||||
}
|
||||
.el-tree-node__content {
|
||||
padding-left: 5px !important;
|
||||
padding-right: 5px;
|
||||
.el-tree-node__expand-icon {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,147 +0,0 @@
|
||||
<template>
|
||||
<div class="default-main ba-table-box">
|
||||
<el-alert class="ba-table-alert" v-if="baTable.table.remark" :title="baTable.table.remark" type="info" show-icon />
|
||||
|
||||
<!-- 表格顶部菜单 -->
|
||||
<TableHeader
|
||||
:buttons="['refresh', 'add', 'comSearch', 'quickSearch', 'columnDisplay']"
|
||||
:quick-search-placeholder="
|
||||
t('Quick search placeholder', { fields: t('user.moneyLog.User name') + '/' + t('user.moneyLog.User nickname') })
|
||||
"
|
||||
>
|
||||
<el-button v-if="!isEmpty(state.userInfo)" v-blur class="table-header-operate">
|
||||
<span class="table-header-operate-text">
|
||||
{{ state.userInfo.username + '(ID:' + state.userInfo.id + ') ' + t('user.moneyLog.balance') + ':' + state.userInfo.money }}
|
||||
</span>
|
||||
</el-button>
|
||||
</TableHeader>
|
||||
|
||||
<!-- 表格 -->
|
||||
<!-- 要使用`el-table`组件原有的属性,直接加在Table标签上即可 -->
|
||||
<Table />
|
||||
|
||||
<!-- 表单 -->
|
||||
<PopupForm />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { debounce, isEmpty, parseInt } from 'lodash-es'
|
||||
import { provide, reactive, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRoute } from 'vue-router'
|
||||
import PopupForm from './popupForm.vue'
|
||||
import { add, url } from '/@/api/backend/user/moneyLog'
|
||||
import { baTableApi } from '/@/api/common'
|
||||
import TableHeader from '/@/components/table/header/index.vue'
|
||||
import Table from '/@/components/table/index.vue'
|
||||
import baTableClass from '/@/utils/baTable'
|
||||
|
||||
defineOptions({
|
||||
name: 'user/moneyLog',
|
||||
})
|
||||
|
||||
const { t } = useI18n()
|
||||
const route = useRoute()
|
||||
const defalutUser = (route.query.user_id ?? '') as string
|
||||
const state = reactive({
|
||||
userInfo: {} as anyObj,
|
||||
})
|
||||
|
||||
const baTable = new baTableClass(
|
||||
new baTableApi(url),
|
||||
{
|
||||
column: [
|
||||
{ type: 'selection', align: 'center', operator: false },
|
||||
{ label: t('Id'), prop: 'id', align: 'center', operator: '=', operatorPlaceholder: t('Id'), width: 70 },
|
||||
{ label: t('user.moneyLog.User ID'), prop: 'user_id', align: 'center', width: 70 },
|
||||
{ label: t('user.moneyLog.User name'), prop: 'user.username', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') },
|
||||
{
|
||||
label: t('user.moneyLog.User nickname'),
|
||||
prop: 'user.nickname',
|
||||
align: 'center',
|
||||
operator: 'LIKE',
|
||||
operatorPlaceholder: t('Fuzzy query'),
|
||||
},
|
||||
{ label: t('user.moneyLog.Change balance'), prop: 'money', align: 'center', operator: 'RANGE', sortable: 'custom' },
|
||||
{ label: t('user.moneyLog.Before change'), prop: 'before', align: 'center', operator: 'RANGE', sortable: 'custom' },
|
||||
{ label: t('user.moneyLog.After change'), prop: 'after', align: 'center', operator: 'RANGE', sortable: 'custom' },
|
||||
{
|
||||
label: t('user.moneyLog.remarks'),
|
||||
prop: 'memo',
|
||||
align: 'center',
|
||||
operator: 'LIKE',
|
||||
operatorPlaceholder: t('Fuzzy query'),
|
||||
showOverflowTooltip: true,
|
||||
},
|
||||
{ label: t('Create time'), prop: 'create_time', align: 'center', render: 'datetime', sortable: 'custom', operator: 'RANGE', width: 160 },
|
||||
],
|
||||
dblClickNotEditColumn: ['all'],
|
||||
},
|
||||
{
|
||||
defaultItems: {
|
||||
user_id: defalutUser,
|
||||
memo: '',
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// 表单提交后
|
||||
baTable.after.onSubmit = () => {
|
||||
getUserInfo(baTable.comSearch.form.user_id)
|
||||
}
|
||||
baTable.after.onTableHeaderAction = ({ event }) => {
|
||||
// 刷新后
|
||||
if (event == 'refresh') {
|
||||
getUserInfo(baTable.comSearch.form.user_id)
|
||||
}
|
||||
}
|
||||
|
||||
baTable.before.onTableAction = ({ event }) => {
|
||||
// 公共搜索
|
||||
if (event === 'com-search') {
|
||||
baTable.table.filter!.search = baTable.getComSearchData()
|
||||
|
||||
for (const key in baTable.table.filter!.search) {
|
||||
if (['money', 'before', 'after'].includes(baTable.table.filter!.search[key].field)) {
|
||||
const val = (baTable.table.filter!.search[key].val as string).split(',')
|
||||
const newVal: (string | number)[] = []
|
||||
for (const k in val) {
|
||||
newVal.push(isNaN(parseFloat(val[k])) ? '' : parseFloat(val[k]) * 100)
|
||||
}
|
||||
baTable.table.filter!.search[key].val = newVal.join(',')
|
||||
}
|
||||
}
|
||||
|
||||
baTable.onTableHeaderAction('refresh', { event: 'com-search', data: baTable.table.filter!.search })
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
baTable.mount()
|
||||
baTable.getData()
|
||||
|
||||
provide('baTable', baTable)
|
||||
|
||||
const getUserInfo = debounce((userId: string) => {
|
||||
if (userId && parseInt(userId) > 0) {
|
||||
add(userId).then((res) => {
|
||||
state.userInfo = res.data.user
|
||||
})
|
||||
} else {
|
||||
state.userInfo = {}
|
||||
}
|
||||
}, 300)
|
||||
|
||||
getUserInfo(baTable.comSearch.form.user_id)
|
||||
|
||||
watch(
|
||||
() => baTable.comSearch.form.user_id,
|
||||
(newVal) => {
|
||||
baTable.form.defaultItems!.user_id = newVal
|
||||
getUserInfo(newVal)
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -1,160 +0,0 @@
|
||||
<template>
|
||||
<!-- 对话框表单 -->
|
||||
<el-dialog
|
||||
class="ba-operate-dialog"
|
||||
:close-on-click-modal="false"
|
||||
:model-value="['Add', 'Edit'].includes(baTable.form.operate!)"
|
||||
@close="baTable.toggleForm"
|
||||
>
|
||||
<template #header>
|
||||
<div class="title" v-drag="['.ba-operate-dialog', '.el-dialog__header']" v-zoom="'.ba-operate-dialog'">
|
||||
{{ baTable.form.operate ? t(baTable.form.operate) : '' }}
|
||||
</div>
|
||||
</template>
|
||||
<el-scrollbar class="ba-table-form-scrollbar">
|
||||
<div
|
||||
class="ba-operate-form"
|
||||
:class="'ba-' + baTable.form.operate + '-form'"
|
||||
:style="config.layout.shrink ? '' : 'width: calc(100% - ' + baTable.form.labelWidth! / 2 + 'px)'"
|
||||
>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
@keyup.enter="baTable.onSubmit(formRef)"
|
||||
:model="baTable.form.items"
|
||||
:label-position="config.layout.shrink ? 'top' : 'right'"
|
||||
:label-width="baTable.form.labelWidth + 'px'"
|
||||
:rules="rules"
|
||||
v-if="!baTable.form.loading"
|
||||
>
|
||||
<FormItem
|
||||
type="remoteSelect"
|
||||
prop="user_id"
|
||||
:label="t('user.moneyLog.User ID')"
|
||||
v-model="baTable.form.items!.user_id"
|
||||
:placeholder="t('Click select')"
|
||||
:input-attr="{
|
||||
pk: 'user.id',
|
||||
field: 'nickname_text',
|
||||
remoteUrl: '/admin/user.User/index',
|
||||
onChange: getAdd,
|
||||
}"
|
||||
/>
|
||||
<el-form-item :label="t('user.moneyLog.User name')">
|
||||
<el-input v-model="state.userInfo.username" disabled></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('user.moneyLog.User nickname')">
|
||||
<el-input v-model="state.userInfo.nickname" disabled></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('user.moneyLog.Current balance')">
|
||||
<el-input v-model="state.userInfo.money" disabled type="number"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="money" :label="t('user.moneyLog.Change amount')">
|
||||
<el-input
|
||||
@input="changeMoney"
|
||||
v-model="baTable.form.items!.money"
|
||||
type="number"
|
||||
:placeholder="t('user.moneyLog.Please enter the balance change amount')"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('user.moneyLog.Balance after change')">
|
||||
<el-input v-model="state.after" type="number" disabled></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="memo" :label="t('user.moneyLog.remarks')">
|
||||
<el-input
|
||||
@keyup.enter.stop=""
|
||||
@keyup.ctrl.enter="baTable.onSubmit(formRef)"
|
||||
v-model="baTable.form.items!.memo"
|
||||
type="textarea"
|
||||
:placeholder="t('user.moneyLog.Please enter change remarks / description')"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
<template #footer>
|
||||
<div :style="'width: calc(100% - ' + baTable.form.labelWidth! / 1.8 + 'px)'">
|
||||
<el-button @click="baTable.toggleForm('')">{{ t('Cancel') }}</el-button>
|
||||
<el-button v-blur :loading="baTable.form.submitLoading" @click="baTable.onSubmit(formRef)" type="primary">
|
||||
{{ baTable.form.operateIds!.length > 1 ? t('Save and edit next item') : t('Save') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, inject, watch, useTemplateRef } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import type baTableClass from '/@/utils/baTable'
|
||||
import { add } from '/@/api/backend/user/moneyLog'
|
||||
import FormItem from '/@/components/formItem/index.vue'
|
||||
import type { FormItemRule } from 'element-plus'
|
||||
import { buildValidatorData } from '/@/utils/validate'
|
||||
import { useConfig } from '/@/stores/config'
|
||||
|
||||
const config = useConfig()
|
||||
const { t } = useI18n()
|
||||
const baTable = inject('baTable') as baTableClass
|
||||
const rules: Partial<Record<string, FormItemRule[]>> = reactive({
|
||||
user_id: [buildValidatorData({ name: 'required', message: t('Please select field', { field: t('user.moneyLog.User') }) })],
|
||||
money: [
|
||||
buildValidatorData({ name: 'required', title: t('user.moneyLog.Change amount') }),
|
||||
{
|
||||
validator: (rule: any, val: string, callback: Function) => {
|
||||
if (!val || parseFloat(val) == 0) {
|
||||
return callback(new Error(t('Please enter the correct field', { field: t('user.moneyLog.Change amount') })))
|
||||
}
|
||||
return callback()
|
||||
},
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
memo: [buildValidatorData({ name: 'required', title: t('user.moneyLog.remarks') })],
|
||||
})
|
||||
|
||||
const formRef = useTemplateRef('formRef')
|
||||
|
||||
const state: {
|
||||
userInfo: anyObj
|
||||
after: number
|
||||
} = reactive({
|
||||
userInfo: {},
|
||||
after: 0,
|
||||
})
|
||||
|
||||
const getAdd = () => {
|
||||
if (!baTable.form.items!.user_id || parseInt(baTable.form.items!.user_id) <= 0) {
|
||||
return
|
||||
}
|
||||
add(baTable.form.items!.user_id).then((res) => {
|
||||
state.userInfo = res.data.user
|
||||
state.after = res.data.user.money
|
||||
})
|
||||
}
|
||||
|
||||
const changeMoney = (value: string) => {
|
||||
if (!state.userInfo || typeof state.userInfo == 'undefined') {
|
||||
state.after = 0
|
||||
return
|
||||
}
|
||||
let newValue = value == '' ? 0 : parseFloat(value)
|
||||
state.after = parseFloat((parseFloat(state.userInfo.money) + newValue).toFixed(2))
|
||||
}
|
||||
|
||||
// 打开表单时刷新用户数据
|
||||
watch(
|
||||
() => baTable.form.operate,
|
||||
(newValue) => {
|
||||
if (newValue) {
|
||||
getAdd()
|
||||
}
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.preview-img {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,108 +0,0 @@
|
||||
<template>
|
||||
<div class="default-main ba-table-box">
|
||||
<el-alert class="ba-table-alert" v-if="baTable.table.remark" :title="baTable.table.remark" type="info" show-icon />
|
||||
|
||||
<!-- 表格顶部菜单 -->
|
||||
<TableHeader
|
||||
:buttons="['refresh', 'add', 'edit', 'delete', 'unfold', 'quickSearch', 'columnDisplay']"
|
||||
:quick-search-placeholder="t('Quick search placeholder', { fields: t('auth.rule.Rule title') })"
|
||||
/>
|
||||
|
||||
<!-- 表格 -->
|
||||
<!-- 要使用`el-table`组件原有的属性,直接加在Table标签上即可 -->
|
||||
<Table ref="tableRef" :pagination="false" />
|
||||
|
||||
<!-- 表单 -->
|
||||
<PopupForm />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, provide, useTemplateRef } from 'vue'
|
||||
import baTableClass from '/@/utils/baTable'
|
||||
import PopupForm from './popupForm.vue'
|
||||
import Table from '/@/components/table/index.vue'
|
||||
import TableHeader from '/@/components/table/header/index.vue'
|
||||
import { defaultOptButtons } from '/@/components/table'
|
||||
import { baTableApi } from '/@/api/common'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
defineOptions({
|
||||
name: 'user/rule',
|
||||
})
|
||||
|
||||
const { t } = useI18n()
|
||||
const tableRef = useTemplateRef('tableRef')
|
||||
|
||||
const baTable = new baTableClass(
|
||||
new baTableApi('/admin/user.Rule/'),
|
||||
{
|
||||
expandAll: false,
|
||||
column: [
|
||||
{ type: 'selection', align: 'center', operator: false },
|
||||
{ label: t('auth.rule.title'), prop: 'title', align: 'left', width: '200' },
|
||||
{ label: t('auth.rule.Icon'), prop: 'icon', align: 'center', width: '60', render: 'icon', default: 'fa fa-circle-o' },
|
||||
{ label: t('auth.rule.name'), prop: 'name', align: 'center', showOverflowTooltip: true },
|
||||
{
|
||||
label: t('auth.rule.type'),
|
||||
prop: 'type',
|
||||
align: 'center',
|
||||
render: 'tag',
|
||||
custom: { menu: 'danger', menu_dir: 'success', route: 'info' },
|
||||
replaceValue: {
|
||||
menu: t('user.rule.Member center menu items'),
|
||||
menu_dir: t('user.rule.Member center menu contents'),
|
||||
route: t('user.rule.Normal routing'),
|
||||
nav: t('user.rule.Top bar menu items'),
|
||||
button: t('user.rule.Page button'),
|
||||
nav_user_menu: t('user.rule.Top bar user dropdown'),
|
||||
},
|
||||
},
|
||||
{ label: t('State'), prop: 'status', align: 'center', width: '80', render: 'switch' },
|
||||
{ label: t('Update time'), prop: 'update_time', align: 'center', width: '160', render: 'datetime' },
|
||||
{ label: t('Create time'), prop: 'create_time', align: 'center', width: '160', render: 'datetime' },
|
||||
{ label: t('Operate'), align: 'center', width: '130', render: 'buttons', buttons: defaultOptButtons() },
|
||||
],
|
||||
dblClickNotEditColumn: [undefined, 'status'],
|
||||
},
|
||||
{
|
||||
defaultItems: {
|
||||
type: 'route',
|
||||
menu_type: 'tab',
|
||||
extend: 'none',
|
||||
no_login_valid: '0',
|
||||
keepalive: 0,
|
||||
status: 1,
|
||||
icon: 'fa fa-circle-o',
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// 表单提交前
|
||||
baTable.before.onSubmit = () => {
|
||||
if (baTable.form.items!.type == 'route') {
|
||||
baTable.form.items!.menu_type = 'tab'
|
||||
} else if (['menu', 'menu_dir', 'nav_user_menu'].includes(baTable.form.items!.type)) {
|
||||
baTable.form.items!.no_login_valid = '0'
|
||||
}
|
||||
}
|
||||
|
||||
// 取得编辑行的数据后
|
||||
baTable.after.getEditData = () => {
|
||||
if (baTable.form.items && !baTable.form.items.icon) {
|
||||
baTable.form.items.icon = 'fa fa-circle-o'
|
||||
}
|
||||
}
|
||||
|
||||
provide('baTable', baTable)
|
||||
|
||||
onMounted(() => {
|
||||
baTable.table.ref = tableRef.value
|
||||
baTable.mount()
|
||||
baTable.getData()?.then(() => {
|
||||
baTable.dragSort()
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -1,237 +0,0 @@
|
||||
<template>
|
||||
<!-- 对话框表单 -->
|
||||
<el-dialog
|
||||
class="ba-operate-dialog"
|
||||
top="5vh"
|
||||
:close-on-click-modal="false"
|
||||
:model-value="['Add', 'Edit'].includes(baTable.form.operate!)"
|
||||
@close="baTable.toggleForm"
|
||||
:destroy-on-close="true"
|
||||
>
|
||||
<template #header>
|
||||
<div class="title" v-drag="['.ba-operate-dialog', '.el-dialog__header']" v-zoom="'.ba-operate-dialog'">
|
||||
{{ baTable.form.operate ? t(baTable.form.operate) : '' }}
|
||||
</div>
|
||||
</template>
|
||||
<el-scrollbar v-loading="baTable.form.loading" class="ba-table-form-scrollbar">
|
||||
<div
|
||||
class="ba-operate-form"
|
||||
:class="'ba-' + baTable.form.operate + '-form'"
|
||||
:style="config.layout.shrink ? '' : 'width: calc(100% - ' + baTable.form.labelWidth! / 2 + 'px)'"
|
||||
>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
@keyup.enter="baTable.onSubmit(formRef)"
|
||||
:model="baTable.form.items"
|
||||
:label-position="config.layout.shrink ? 'top' : 'right'"
|
||||
:label-width="baTable.form.labelWidth + 'px'"
|
||||
:rules="rules"
|
||||
v-if="!baTable.form.loading"
|
||||
>
|
||||
<FormItem
|
||||
type="remoteSelect"
|
||||
prop="pid"
|
||||
:label="t('auth.rule.Superior menu rule')"
|
||||
v-model="baTable.form.items!.pid"
|
||||
:placeholder="t('Click select')"
|
||||
:input-attr="{
|
||||
params: { isTree: true },
|
||||
field: 'title',
|
||||
remoteUrl: baTable.api.actionUrl.get('index'),
|
||||
emptyValues: ['', null, undefined, 0],
|
||||
valueOnClear: 0,
|
||||
}"
|
||||
/>
|
||||
<el-form-item :label="t('auth.rule.Rule type')">
|
||||
<el-radio-group v-model="baTable.form.items!.type">
|
||||
<el-radio class="ba-el-radio" value="route" :border="true">{{ t('user.rule.Normal routing') }}</el-radio>
|
||||
<el-radio class="ba-el-radio" value="menu_dir" :border="true">{{ t('user.rule.Member center menu contents') }}</el-radio>
|
||||
<el-radio class="ba-el-radio" value="menu" :border="true">{{ t('user.rule.Member center menu items') }}</el-radio>
|
||||
<el-radio class="ba-el-radio" value="nav" :border="true">{{ t('user.rule.Top bar menu items') }}</el-radio>
|
||||
<el-radio class="ba-el-radio" value="button" :border="true">{{ t('user.rule.Page button') }}</el-radio>
|
||||
<el-radio class="ba-el-radio" value="nav_user_menu" :border="true">{{ t('user.rule.Top bar user dropdown') }}</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="block-help">{{ t('user.rule.Type ' + baTable.form.items!.type + ' tips') }}</div>
|
||||
</el-form-item>
|
||||
<el-form-item prop="title" :label="t('auth.rule.Rule title')">
|
||||
<el-input
|
||||
v-model="baTable.form.items!.title"
|
||||
type="string"
|
||||
:placeholder="t('Please input field', { field: t('auth.rule.Rule title') })"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="name" :label="t('auth.rule.Rule name')">
|
||||
<el-input v-model="baTable.form.items!.name" type="string" :placeholder="t('user.rule.English name')"></el-input>
|
||||
<div class="block-help">
|
||||
{{ t('auth.rule.It will be registered as the web side routing name and used as the server side API authentication') }}
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="baTable.form.items!.type != 'button'" prop="path" :label="t('auth.rule.Routing path')">
|
||||
<el-input v-model="baTable.form.items!.path" type="string" :placeholder="t('user.rule.Web side routing path')"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 规则图标 -->
|
||||
<FormItem
|
||||
v-if="baTable.form.items!.type != 'button'"
|
||||
type="icon"
|
||||
:label="t('auth.rule.Rule Icon')"
|
||||
v-model="baTable.form.items!.icon"
|
||||
:input-attr="{ showIconName: true }"
|
||||
/>
|
||||
<!-- 菜单类型:tab、link、iframe -->
|
||||
<FormItem
|
||||
v-if="!['menu_dir', 'button', 'route'].includes(baTable.form.items!.type)"
|
||||
:label="t('auth.rule.Menu type')"
|
||||
v-model="baTable.form.items!.menu_type"
|
||||
type="radio"
|
||||
:input-attr="{
|
||||
border: true,
|
||||
content: { tab: t('auth.rule.Menu type tab'), link: t('auth.rule.Menu type link (offsite)'), iframe: 'Iframe' },
|
||||
}"
|
||||
/>
|
||||
<!-- URL -->
|
||||
<el-form-item
|
||||
prop="url"
|
||||
v-if="!['menu_dir', 'button', 'route'].includes(baTable.form.items!.type) && baTable.form.items!.menu_type != 'tab'"
|
||||
:label="t('auth.rule.Link address')"
|
||||
>
|
||||
<el-input
|
||||
v-model="baTable.form.items!.url"
|
||||
type="string"
|
||||
:placeholder="t('auth.rule.Please enter the URL address of the link or iframe')"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<!-- 组件路径 -->
|
||||
<el-form-item
|
||||
v-if="
|
||||
baTable.form.items!.type == 'route' ||
|
||||
(!['menu_dir', 'button'].includes(baTable.form.items!.type) && baTable.form.items!.menu_type == 'tab')
|
||||
"
|
||||
:label="t('auth.rule.Component path')"
|
||||
>
|
||||
<el-input
|
||||
v-model="baTable.form.items!.component"
|
||||
type="string"
|
||||
:placeholder="t('user.rule.For example, if you add account/overview as a route only')"
|
||||
></el-input>
|
||||
<div class="block-help component-path-tips">
|
||||
{{ t('user.rule.Component path tips') }}
|
||||
</div>
|
||||
</el-form-item>
|
||||
<!-- 扩展属性 -->
|
||||
<el-form-item
|
||||
v-if="!['menu_dir', 'button'].includes(baTable.form.items!.type) && baTable.form.items!.menu_type == 'tab'"
|
||||
:label="t('auth.rule.Extended properties')"
|
||||
>
|
||||
<el-select
|
||||
class="w100"
|
||||
v-model="baTable.form.items!.extend"
|
||||
:placeholder="t('Please select field', { field: t('auth.rule.Extended properties') })"
|
||||
>
|
||||
<el-option :label="t('auth.rule.none')" value="none"></el-option>
|
||||
<el-option :label="t('auth.rule.Add as route only')" value="add_rules_only"></el-option>
|
||||
<el-option :label="t('auth.rule.Add as menu only')" value="add_menu_only"></el-option>
|
||||
</el-select>
|
||||
<div class="block-help">
|
||||
{{ t('user.rule.Web side component path, please start with /src, such as: /src/views/frontend/index') }}
|
||||
</div>
|
||||
</el-form-item>
|
||||
<FormItem
|
||||
v-if="!['menu_dir', 'menu', 'nav_user_menu'].includes(baTable.form.items!.type)"
|
||||
:label="t('user.rule.no_login_valid')"
|
||||
v-model="baTable.form.items!.no_login_valid"
|
||||
type="radio"
|
||||
:input-attr="{
|
||||
border: true,
|
||||
content: { '0': t('user.rule.no_login_valid 0'), '1': t('user.rule.no_login_valid 1') },
|
||||
}"
|
||||
:block-help="t('user.rule.no_login_valid tips')"
|
||||
/>
|
||||
<el-form-item :label="t('auth.rule.Rule comments')">
|
||||
<el-input
|
||||
@keyup.enter.stop=""
|
||||
@keyup.ctrl.enter="baTable.onSubmit(formRef)"
|
||||
v-model="baTable.form.items!.remark"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 5 }"
|
||||
:placeholder="t('Please input field', { field: t('auth.rule.Rule comments') })"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('auth.rule.Rule weight')">
|
||||
<el-input
|
||||
v-model="baTable.form.items!.weigh"
|
||||
type="number"
|
||||
:placeholder="t('auth.rule.Please enter the weight of menu rule (sort by)')"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<FormItem
|
||||
:label="t('State')"
|
||||
v-model="baTable.form.items!.status"
|
||||
type="radio"
|
||||
:input-attr="{
|
||||
border: true,
|
||||
content: { 0: t('Disable'), 1: t('Enable') },
|
||||
}"
|
||||
/>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
<template #footer>
|
||||
<div :style="'width: calc(100% - ' + baTable.form.labelWidth! / 1.8 + 'px)'">
|
||||
<el-button @click="baTable.toggleForm('')">{{ t('Cancel') }}</el-button>
|
||||
<el-button v-blur :loading="baTable.form.submitLoading" @click="baTable.onSubmit(formRef)" type="primary">
|
||||
{{ baTable.form.operateIds && baTable.form.operateIds.length > 1 ? t('Save and edit next item') : t('Save') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, inject, useTemplateRef } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import type baTableClass from '/@/utils/baTable'
|
||||
import FormItem from '/@/components/formItem/index.vue'
|
||||
import type { FormItemRule } from 'element-plus'
|
||||
import { buildValidatorData } from '/@/utils/validate'
|
||||
import { useConfig } from '/@/stores/config'
|
||||
|
||||
const config = useConfig()
|
||||
const formRef = useTemplateRef('formRef')
|
||||
const baTable = inject('baTable') as baTableClass
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const rules: Partial<Record<string, FormItemRule[]>> = reactive({
|
||||
title: [buildValidatorData({ name: 'required', title: t('auth.rule.Rule title') })],
|
||||
pid: [
|
||||
{
|
||||
validator: (rule: any, val: string, callback: Function) => {
|
||||
if (!val) {
|
||||
return callback()
|
||||
}
|
||||
if (parseInt(val) == parseInt(baTable.form.items!.id)) {
|
||||
return callback(new Error(t('auth.rule.The superior menu rule cannot be the rule itself')))
|
||||
}
|
||||
return callback()
|
||||
},
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
name: [buildValidatorData({ name: 'required', title: t('auth.rule.Rule name') })],
|
||||
path: [buildValidatorData({ name: 'required', title: t('auth.rule.Routing path') })],
|
||||
url: [
|
||||
buildValidatorData({ name: 'required', message: t('auth.rule.Link address') }),
|
||||
buildValidatorData({ name: 'url', message: t('auth.rule.Please enter the correct URL') }),
|
||||
],
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.ba-el-radio {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.component-path-tips {
|
||||
color: var(--el-color-warning);
|
||||
}
|
||||
</style>
|
||||
@@ -1,126 +0,0 @@
|
||||
<template>
|
||||
<div class="default-main ba-table-box">
|
||||
<el-alert class="ba-table-alert" v-if="baTable.table.remark" :title="baTable.table.remark" type="info" show-icon />
|
||||
|
||||
<!-- 表格顶部菜单 -->
|
||||
<TableHeader
|
||||
:buttons="['refresh', 'add', 'comSearch', 'quickSearch', 'columnDisplay']"
|
||||
:quick-search-placeholder="
|
||||
t('Quick search placeholder', { fields: t('user.moneyLog.User name') + '/' + t('user.moneyLog.User nickname') })
|
||||
"
|
||||
>
|
||||
<el-button v-if="!isEmpty(state.userInfo)" v-blur class="table-header-operate">
|
||||
<span class="table-header-operate-text">
|
||||
{{ state.userInfo.username + '(ID:' + state.userInfo.id + ') ' + t('user.scoreLog.integral') + ':' + state.userInfo.score }}
|
||||
</span>
|
||||
</el-button>
|
||||
</TableHeader>
|
||||
|
||||
<!-- 表格 -->
|
||||
<!-- 要使用`el-table`组件原有的属性,直接加在Table标签上即可 -->
|
||||
<Table />
|
||||
|
||||
<!-- 表单 -->
|
||||
<PopupForm />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { debounce, isEmpty, parseInt } from 'lodash-es'
|
||||
import { provide, reactive, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRoute } from 'vue-router'
|
||||
import PopupForm from './popupForm.vue'
|
||||
import { add, url } from '/@/api/backend/user/scoreLog'
|
||||
import { baTableApi } from '/@/api/common'
|
||||
import TableHeader from '/@/components/table/header/index.vue'
|
||||
import Table from '/@/components/table/index.vue'
|
||||
import baTableClass from '/@/utils/baTable'
|
||||
|
||||
defineOptions({
|
||||
name: 'user/scoreLog',
|
||||
})
|
||||
|
||||
const { t } = useI18n()
|
||||
const route = useRoute()
|
||||
const defalutUser = (route.query.user_id ?? '') as string
|
||||
const state = reactive({
|
||||
userInfo: {} as anyObj,
|
||||
})
|
||||
|
||||
const baTable = new baTableClass(
|
||||
new baTableApi(url),
|
||||
{
|
||||
column: [
|
||||
{ type: 'selection', align: 'center', operator: false },
|
||||
{ label: t('Id'), prop: 'id', align: 'center', operator: '=', operatorPlaceholder: t('Id'), width: 70 },
|
||||
{ label: t('user.moneyLog.User ID'), prop: 'user_id', align: 'center', width: 70 },
|
||||
{ label: t('user.moneyLog.User name'), prop: 'user.username', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') },
|
||||
{
|
||||
label: t('user.moneyLog.User nickname'),
|
||||
prop: 'user.nickname',
|
||||
align: 'center',
|
||||
operator: 'LIKE',
|
||||
operatorPlaceholder: t('Fuzzy query'),
|
||||
},
|
||||
{ label: t('user.scoreLog.Change points'), prop: 'score', align: 'center', operator: 'RANGE', sortable: 'custom' },
|
||||
{ label: t('user.moneyLog.Before change'), prop: 'before', align: 'center', operator: 'RANGE', sortable: 'custom' },
|
||||
{ label: t('user.moneyLog.After change'), prop: 'after', align: 'center', operator: 'RANGE', sortable: 'custom' },
|
||||
{
|
||||
label: t('user.moneyLog.remarks'),
|
||||
prop: 'memo',
|
||||
align: 'center',
|
||||
operator: 'LIKE',
|
||||
operatorPlaceholder: t('Fuzzy query'),
|
||||
showOverflowTooltip: true,
|
||||
},
|
||||
{ label: t('Create time'), prop: 'create_time', align: 'center', render: 'datetime', sortable: 'custom', operator: 'RANGE', width: 160 },
|
||||
],
|
||||
dblClickNotEditColumn: ['all'],
|
||||
},
|
||||
{
|
||||
defaultItems: {
|
||||
user_id: defalutUser,
|
||||
memo: '',
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// 表单提交后
|
||||
baTable.after.onSubmit = () => {
|
||||
getUserInfo(baTable.comSearch.form.user_id)
|
||||
}
|
||||
baTable.after.onTableHeaderAction = ({ event }) => {
|
||||
// 刷新后
|
||||
if (event == 'refresh') {
|
||||
getUserInfo(baTable.comSearch.form.user_id)
|
||||
}
|
||||
}
|
||||
|
||||
baTable.mount()
|
||||
baTable.getData()
|
||||
|
||||
provide('baTable', baTable)
|
||||
|
||||
const getUserInfo = debounce((userId: string) => {
|
||||
if (userId && parseInt(userId) > 0) {
|
||||
add(userId).then((res) => {
|
||||
state.userInfo = res.data.user
|
||||
})
|
||||
} else {
|
||||
state.userInfo = {}
|
||||
}
|
||||
}, 300)
|
||||
|
||||
getUserInfo(baTable.comSearch.form.user_id)
|
||||
|
||||
watch(
|
||||
() => baTable.comSearch.form.user_id,
|
||||
(newVal) => {
|
||||
baTable.form.defaultItems!.user_id = newVal
|
||||
getUserInfo(newVal)
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -1,160 +0,0 @@
|
||||
<template>
|
||||
<!-- 对话框表单 -->
|
||||
<el-dialog
|
||||
class="ba-operate-dialog"
|
||||
:close-on-click-modal="false"
|
||||
:model-value="['Add', 'Edit'].includes(baTable.form.operate!)"
|
||||
@close="baTable.toggleForm"
|
||||
>
|
||||
<template #header>
|
||||
<div class="title" v-drag="['.ba-operate-dialog', '.el-dialog__header']" v-zoom="'.ba-operate-dialog'">
|
||||
{{ baTable.form.operate ? t(baTable.form.operate) : '' }}
|
||||
</div>
|
||||
</template>
|
||||
<el-scrollbar class="ba-table-form-scrollbar">
|
||||
<div
|
||||
class="ba-operate-form"
|
||||
:class="'ba-' + baTable.form.operate + '-form'"
|
||||
:style="config.layout.shrink ? '' : 'width: calc(100% - ' + baTable.form.labelWidth! / 2 + 'px)'"
|
||||
>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
@keyup.enter="baTable.onSubmit(formRef)"
|
||||
:model="baTable.form.items"
|
||||
:label-position="config.layout.shrink ? 'top' : 'right'"
|
||||
:label-width="baTable.form.labelWidth + 'px'"
|
||||
:rules="rules"
|
||||
v-if="!baTable.form.loading"
|
||||
>
|
||||
<FormItem
|
||||
type="remoteSelect"
|
||||
prop="user_id"
|
||||
:label="t('user.moneyLog.User ID')"
|
||||
v-model="baTable.form.items!.user_id"
|
||||
:placeholder="t('Click select')"
|
||||
:input-attr="{
|
||||
pk: 'user.id',
|
||||
field: 'nickname_text',
|
||||
remoteUrl: '/admin/user.User/index',
|
||||
onChange: getAdd,
|
||||
}"
|
||||
/>
|
||||
<el-form-item :label="t('user.moneyLog.User name')">
|
||||
<el-input v-model="state.userInfo.username" disabled></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('user.moneyLog.User nickname')">
|
||||
<el-input v-model="state.userInfo.nickname" disabled></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('user.scoreLog.Current points')">
|
||||
<el-input v-model="state.userInfo.score" disabled type="number"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="score" :label="t('user.moneyLog.Change amount')">
|
||||
<el-input
|
||||
@input="changeScore"
|
||||
v-model="baTable.form.items!.score"
|
||||
type="number"
|
||||
:placeholder="t('user.scoreLog.Please enter the change amount of points')"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('user.scoreLog.Points after change')">
|
||||
<el-input v-model="state.after" type="number" disabled></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="memo" :label="t('user.moneyLog.remarks')">
|
||||
<el-input
|
||||
@keyup.enter.stop=""
|
||||
@keyup.ctrl.enter="baTable.onSubmit(formRef)"
|
||||
v-model="baTable.form.items!.memo"
|
||||
type="textarea"
|
||||
:placeholder="t('user.scoreLog.Please enter change remarks / description')"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
<template #footer>
|
||||
<div :style="'width: calc(100% - ' + baTable.form.labelWidth! / 1.8 + 'px)'">
|
||||
<el-button @click="baTable.toggleForm('')">{{ t('Cancel') }}</el-button>
|
||||
<el-button v-blur :loading="baTable.form.submitLoading" @click="baTable.onSubmit(formRef)" type="primary">
|
||||
{{ baTable.form.operateIds!.length > 1 ? t('Save and edit next item') : t('Save') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, inject, watch, useTemplateRef } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import type baTableClass from '/@/utils/baTable'
|
||||
import { add } from '/@/api/backend/user/scoreLog'
|
||||
import FormItem from '/@/components/formItem/index.vue'
|
||||
import type { FormItemRule } from 'element-plus'
|
||||
import { buildValidatorData } from '/@/utils/validate'
|
||||
import { useConfig } from '/@/stores/config'
|
||||
|
||||
const config = useConfig()
|
||||
const { t } = useI18n()
|
||||
const baTable = inject('baTable') as baTableClass
|
||||
const rules: Partial<Record<string, FormItemRule[]>> = reactive({
|
||||
user_id: [buildValidatorData({ name: 'required', message: t('Please select field', { field: t('user.moneyLog.User') }) })],
|
||||
score: [
|
||||
buildValidatorData({ name: 'required', title: t('user.moneyLog.Change amount') }),
|
||||
{
|
||||
validator: (rule: any, val: string, callback: Function) => {
|
||||
if (!val || parseInt(val) == 0) {
|
||||
return callback(new Error(t('Please enter the correct field', { field: t('user.moneyLog.Change amount') })))
|
||||
}
|
||||
return callback()
|
||||
},
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
memo: [buildValidatorData({ name: 'required', title: t('user.moneyLog.remarks') })],
|
||||
})
|
||||
|
||||
const formRef = useTemplateRef('formRef')
|
||||
|
||||
const state: {
|
||||
userInfo: anyObj
|
||||
after: number
|
||||
} = reactive({
|
||||
userInfo: {},
|
||||
after: 0,
|
||||
})
|
||||
|
||||
const getAdd = () => {
|
||||
if (!baTable.form.items!.user_id || parseInt(baTable.form.items!.user_id) <= 0) {
|
||||
return
|
||||
}
|
||||
add(baTable.form.items!.user_id).then((res) => {
|
||||
state.userInfo = res.data.user
|
||||
state.after = res.data.user.score
|
||||
})
|
||||
}
|
||||
|
||||
const changeScore = (value: string) => {
|
||||
if (!state.userInfo || typeof state.userInfo == 'undefined') {
|
||||
state.after = 0
|
||||
return
|
||||
}
|
||||
let newValue = value == '' ? 0 : parseFloat(value)
|
||||
state.after = parseFloat(state.userInfo.score) + newValue
|
||||
}
|
||||
|
||||
// 打开表单时刷新用户数据
|
||||
watch(
|
||||
() => baTable.form.operate,
|
||||
(newValue) => {
|
||||
if (newValue) {
|
||||
getAdd()
|
||||
}
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.preview-img {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,114 +0,0 @@
|
||||
<template>
|
||||
<div class="default-main ba-table-box">
|
||||
<el-alert class="ba-table-alert" v-if="baTable.table.remark" :title="baTable.table.remark" type="info" show-icon />
|
||||
|
||||
<!-- 表格顶部菜单 -->
|
||||
<TableHeader
|
||||
:buttons="['refresh', 'add', 'edit', 'delete', 'comSearch', 'quickSearch', 'columnDisplay']"
|
||||
:quick-search-placeholder="t('Quick search placeholder', { fields: t('user.user.User name') + '/' + t('user.user.nickname') })"
|
||||
/>
|
||||
|
||||
<!-- 表格 -->
|
||||
<!-- 要使用`el-table`组件原有的属性,直接加在Table标签上即可 -->
|
||||
<Table />
|
||||
|
||||
<!-- 表单 -->
|
||||
<PopupForm />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { provide } from 'vue'
|
||||
import baTableClass from '/@/utils/baTable'
|
||||
import PopupForm from './popupForm.vue'
|
||||
import Table from '/@/components/table/index.vue'
|
||||
import TableHeader from '/@/components/table/header/index.vue'
|
||||
import { defaultOptButtons } from '/@/components/table'
|
||||
import { baTableApi } from '/@/api/common'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
defineOptions({
|
||||
name: 'user/user',
|
||||
})
|
||||
|
||||
const { t } = useI18n()
|
||||
const baTable = new baTableClass(
|
||||
new baTableApi('/admin/user.User/'),
|
||||
{
|
||||
column: [
|
||||
{ type: 'selection', align: 'center', operator: false },
|
||||
{ label: t('Id'), prop: 'id', align: 'center', operator: '=', operatorPlaceholder: t('Id'), width: 70 },
|
||||
{ label: t('user.user.User name'), prop: 'username', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') },
|
||||
{ label: t('user.user.nickname'), prop: 'nickname', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') },
|
||||
{
|
||||
label: t('user.user.group'),
|
||||
prop: 'userGroup.name',
|
||||
align: 'center',
|
||||
operator: 'LIKE',
|
||||
operatorPlaceholder: t('Fuzzy query'),
|
||||
render: 'tag',
|
||||
},
|
||||
{ label: t('user.user.avatar'), prop: 'avatar', align: 'center', render: 'image', operator: false },
|
||||
{
|
||||
label: t('user.user.Gender'),
|
||||
prop: 'gender',
|
||||
align: 'center',
|
||||
render: 'tag',
|
||||
custom: { '0': 'info', '1': '', '2': 'success' },
|
||||
replaceValue: { '0': t('Unknown'), '1': t('user.user.male'), '2': t('user.user.female') },
|
||||
},
|
||||
{ label: t('user.user.mobile'), prop: 'mobile', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') },
|
||||
{
|
||||
label: t('user.user.Last login IP'),
|
||||
prop: 'last_login_ip',
|
||||
align: 'center',
|
||||
operator: 'LIKE',
|
||||
operatorPlaceholder: t('Fuzzy query'),
|
||||
render: 'tag',
|
||||
},
|
||||
{
|
||||
label: t('user.user.Last login'),
|
||||
prop: 'last_login_time',
|
||||
align: 'center',
|
||||
render: 'datetime',
|
||||
sortable: 'custom',
|
||||
operator: 'RANGE',
|
||||
width: 160,
|
||||
},
|
||||
{ label: t('Create time'), prop: 'create_time', align: 'center', render: 'datetime', sortable: 'custom', operator: 'RANGE', width: 160 },
|
||||
{
|
||||
label: t('State'),
|
||||
prop: 'status',
|
||||
align: 'center',
|
||||
render: 'tag',
|
||||
custom: { disable: 'danger', enable: 'success' },
|
||||
replaceValue: { disable: t('Disable'), enable: t('Enable') },
|
||||
},
|
||||
{
|
||||
label: t('Operate'),
|
||||
align: 'center',
|
||||
width: '100',
|
||||
render: 'buttons',
|
||||
buttons: defaultOptButtons(['edit', 'delete']),
|
||||
operator: false,
|
||||
},
|
||||
],
|
||||
dblClickNotEditColumn: [undefined],
|
||||
},
|
||||
{
|
||||
defaultItems: {
|
||||
gender: 0,
|
||||
money: '0',
|
||||
score: '0',
|
||||
status: 'enable',
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
baTable.mount()
|
||||
baTable.getData()
|
||||
|
||||
provide('baTable', baTable)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -1,238 +0,0 @@
|
||||
<template>
|
||||
<!-- 对话框表单 -->
|
||||
<el-dialog
|
||||
class="ba-operate-dialog"
|
||||
:close-on-click-modal="false"
|
||||
:destroy-on-close="true"
|
||||
:model-value="['Add', 'Edit'].includes(baTable.form.operate!)"
|
||||
@close="baTable.toggleForm"
|
||||
>
|
||||
<template #header>
|
||||
<div class="title" v-drag="['.ba-operate-dialog', '.el-dialog__header']" v-zoom="'.ba-operate-dialog'">
|
||||
{{ baTable.form.operate ? t(baTable.form.operate) : '' }}
|
||||
</div>
|
||||
</template>
|
||||
<el-scrollbar v-loading="baTable.form.loading" class="ba-table-form-scrollbar">
|
||||
<div
|
||||
class="ba-operate-form"
|
||||
:class="'ba-' + baTable.form.operate + '-form'"
|
||||
:style="config.layout.shrink ? '' : 'width: calc(100% - ' + baTable.form.labelWidth! / 2 + 'px)'"
|
||||
>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
@keyup.enter="baTable.onSubmit(formRef)"
|
||||
:model="baTable.form.items"
|
||||
:label-position="config.layout.shrink ? 'top' : 'right'"
|
||||
:label-width="baTable.form.labelWidth + 'px'"
|
||||
:rules="rules"
|
||||
v-if="!baTable.form.loading"
|
||||
>
|
||||
<el-form-item prop="username" :label="t('user.user.User name')">
|
||||
<el-input
|
||||
v-model="baTable.form.items!.username"
|
||||
type="string"
|
||||
:placeholder="t('Please input field', { field: t('user.user.User name') + '(' + t('user.user.Login account') + ')' })"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="nickname" :label="t('user.user.nickname')">
|
||||
<el-input
|
||||
v-model="baTable.form.items!.nickname"
|
||||
type="string"
|
||||
:placeholder="t('Please input field', { field: t('user.user.nickname') })"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<FormItem
|
||||
type="remoteSelect"
|
||||
:label="t('user.user.group')"
|
||||
v-model="baTable.form.items!.group_id"
|
||||
prop="group_id"
|
||||
:placeholder="t('user.user.group')"
|
||||
:input-attr="{
|
||||
params: { isTree: true, search: [{ field: 'status', val: '1', operator: 'eq' }] },
|
||||
field: 'name',
|
||||
remoteUrl: '/admin/user.Group/index',
|
||||
}"
|
||||
/>
|
||||
<FormItem :label="t('user.user.avatar')" type="image" v-model="baTable.form.items!.avatar" />
|
||||
<el-form-item prop="email" :label="t('user.user.email')">
|
||||
<el-input
|
||||
v-model="baTable.form.items!.email"
|
||||
type="string"
|
||||
:placeholder="t('Please input field', { field: t('user.user.email') })"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="mobile" :label="t('user.user.mobile')">
|
||||
<el-input
|
||||
v-model="baTable.form.items!.mobile"
|
||||
type="string"
|
||||
:placeholder="t('Please input field', { field: t('user.user.mobile') })"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<FormItem
|
||||
:label="t('user.user.Gender')"
|
||||
v-model="baTable.form.items!.gender"
|
||||
type="radio"
|
||||
:input-attr="{
|
||||
border: true,
|
||||
content: { 0: t('Unknown'), 1: t('user.user.male'), 2: t('user.user.female') },
|
||||
}"
|
||||
/>
|
||||
<el-form-item :label="t('user.user.birthday')">
|
||||
<el-date-picker
|
||||
class="w100"
|
||||
value-format="YYYY-MM-DD"
|
||||
v-model="baTable.form.items!.birthday"
|
||||
type="date"
|
||||
:placeholder="t('Please select field', { field: t('user.user.birthday') })"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="baTable.form.operate == 'Edit'" :label="t('user.user.balance')">
|
||||
<el-input v-model="baTable.form.items!.money" readonly>
|
||||
<template #append>
|
||||
<el-button @click="changeAccount('money')">{{ t('user.user.Adjustment balance') }}</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="baTable.form.operate == 'Edit'" :label="t('user.user.integral')">
|
||||
<el-input v-model="baTable.form.items!.score" readonly>
|
||||
<template #append>
|
||||
<el-button @click="changeAccount('score')">{{ t('user.user.Adjust integral') }}</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password" :label="t('user.user.password')">
|
||||
<el-input
|
||||
v-model="baTable.form.items!.password"
|
||||
type="password"
|
||||
autocomplete="new-password"
|
||||
:placeholder="
|
||||
baTable.form.operate == 'Add'
|
||||
? t('Please input field', { field: t('user.user.password') })
|
||||
: t('user.user.Please leave blank if not modified')
|
||||
"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="motto" :label="t('user.user.Personal signature')">
|
||||
<el-input
|
||||
@keyup.enter.stop=""
|
||||
@keyup.ctrl.enter="baTable.onSubmit(formRef)"
|
||||
v-model="baTable.form.items!.motto"
|
||||
type="textarea"
|
||||
:placeholder="t('Please input field', { field: t('user.user.Personal signature') })"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<FormItem
|
||||
:label="t('State')"
|
||||
v-model="baTable.form.items!.status"
|
||||
type="radio"
|
||||
:input-attr="{
|
||||
border: true,
|
||||
content: { disable: t('Disable'), enable: t('Enable') },
|
||||
}"
|
||||
/>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
<template #footer>
|
||||
<div :style="'width: calc(100% - ' + baTable.form.labelWidth! / 1.8 + 'px)'">
|
||||
<el-button @click="baTable.toggleForm('')">{{ t('Cancel') }}</el-button>
|
||||
<el-button v-blur :loading="baTable.form.submitLoading" @click="baTable.onSubmit(formRef)" type="primary">
|
||||
{{ baTable.form.operateIds && baTable.form.operateIds.length > 1 ? t('Save and edit next item') : t('Save') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, inject, watch, useTemplateRef } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import type baTableClass from '/@/utils/baTable'
|
||||
import { regularPassword } from '/@/utils/validate'
|
||||
import type { FormItemRule } from 'element-plus'
|
||||
import FormItem from '/@/components/formItem/index.vue'
|
||||
import router from '/@/router/index'
|
||||
import { buildValidatorData } from '/@/utils/validate'
|
||||
import { useConfig } from '/@/stores/config'
|
||||
|
||||
const config = useConfig()
|
||||
const formRef = useTemplateRef('formRef')
|
||||
const baTable = inject('baTable') as baTableClass
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const rules: Partial<Record<string, FormItemRule[]>> = reactive({
|
||||
username: [buildValidatorData({ name: 'required', title: t('user.user.User name') }), buildValidatorData({ name: 'account' })],
|
||||
nickname: [buildValidatorData({ name: 'required', title: t('user.user.nickname') })],
|
||||
group_id: [buildValidatorData({ name: 'required', message: t('Please select field', { field: t('user.user.group') }) })],
|
||||
email: [buildValidatorData({ name: 'email', title: t('user.user.email') })],
|
||||
mobile: [buildValidatorData({ name: 'mobile' })],
|
||||
password: [
|
||||
{
|
||||
validator: (rule: any, val: string, callback: Function) => {
|
||||
if (baTable.form.operate == 'Add') {
|
||||
if (!val) {
|
||||
return callback(new Error(t('Please input field', { field: t('user.user.password') })))
|
||||
}
|
||||
} else {
|
||||
if (!val) {
|
||||
return callback()
|
||||
}
|
||||
}
|
||||
if (!regularPassword(val)) {
|
||||
return callback(new Error(t('validate.Please enter the correct password')))
|
||||
}
|
||||
return callback()
|
||||
},
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const changeAccount = (type: string) => {
|
||||
baTable.toggleForm()
|
||||
router.push({
|
||||
name: type == 'money' ? 'user/moneyLog' : 'user/scoreLog',
|
||||
query: {
|
||||
user_id: baTable.form.items!.id,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
watch(
|
||||
() => baTable.form.operate,
|
||||
(newVal) => {
|
||||
rules.password![0].required = newVal == 'Add'
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.avatar-uploader {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
border-radius: var(--el-border-radius-small);
|
||||
box-shadow: var(--el-box-shadow-light);
|
||||
border: 1px dashed var(--el-border-color);
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
width: 110px;
|
||||
height: 110px;
|
||||
}
|
||||
.avatar-uploader:hover {
|
||||
border-color: var(--el-color-primary);
|
||||
}
|
||||
.avatar {
|
||||
width: 110px;
|
||||
height: 110px;
|
||||
display: block;
|
||||
}
|
||||
.image-slot {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user