[会员管理]-移除
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 ba\Filesystem;
|
||||||
use app\common\controller\Api;
|
use app\common\controller\Api;
|
||||||
use app\admin\model\Admin as AdminModel;
|
use app\admin\model\Admin as AdminModel;
|
||||||
use app\admin\model\User as UserModel;
|
|
||||||
use app\process\Monitor;
|
use app\process\Monitor;
|
||||||
use support\Response;
|
use support\Response;
|
||||||
use Webman\Http\Request;
|
use Webman\Http\Request;
|
||||||
@@ -627,10 +626,6 @@ class Install extends Api
|
|||||||
$adminModel->resetPassword($defaultAdmin->id, $param['adminpassword']);
|
$adminModel->resetPassword($defaultAdmin->id, $param['adminpassword']);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 默认用户密码修改
|
|
||||||
$user = new UserModel();
|
|
||||||
$user->resetPassword(1, Random::build());
|
|
||||||
|
|
||||||
// 修改站点名称
|
// 修改站点名称
|
||||||
if (class_exists(\app\admin\model\Config::class)) {
|
if (class_exists(\app\admin\model\Config::class)) {
|
||||||
\app\admin\model\Config::where('name', 'site_name')->update([
|
\app\admin\model\Config::where('name', 'site_name')->update([
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use ba\Captcha;
|
|||||||
use ba\ClickCaptcha;
|
use ba\ClickCaptcha;
|
||||||
use app\common\controller\Frontend;
|
use app\common\controller\Frontend;
|
||||||
use app\common\facade\Token;
|
use app\common\facade\Token;
|
||||||
|
use support\think\Db;
|
||||||
use support\validation\Validator;
|
use support\validation\Validator;
|
||||||
use support\validation\ValidationException;
|
use support\validation\ValidationException;
|
||||||
use Webman\Http\Request;
|
use Webman\Http\Request;
|
||||||
@@ -46,6 +47,7 @@ class User extends Frontend
|
|||||||
'captchaId' => $params['captchaId'] ?? '',
|
'captchaId' => $params['captchaId'] ?? '',
|
||||||
'captchaInfo' => $params['captchaInfo'] ?? '',
|
'captchaInfo' => $params['captchaInfo'] ?? '',
|
||||||
'registerType' => $params['registerType'] ?? '',
|
'registerType' => $params['registerType'] ?? '',
|
||||||
|
'invite_code' => $params['invite_code'] ?? '',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (!in_array($params['tab'], ['login', 'register'])) {
|
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')) {
|
if (!$captchaObj->check($params['captcha'], $params[$params['registerType']] . 'user_register')) {
|
||||||
return $this->error(__('Please enter the correct verification code'));
|
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) {
|
if ($res === true) {
|
||||||
@@ -117,6 +132,7 @@ class User extends Frontend
|
|||||||
'email' => 'required_if:registerType,email|email|unique:user,email',
|
'email' => 'required_if:registerType,email|email|unique:user,email',
|
||||||
'mobile' => 'required_if:registerType,mobile|regex:/^1[3-9]\d{9}$/|unique:user,mobile',
|
'mobile' => 'required_if:registerType,mobile|regex:/^1[3-9]\d{9}$/|unique:user,mobile',
|
||||||
'captcha' => 'required|string',
|
'captcha' => 'required|string',
|
||||||
|
'invite_code' => 'nullable|string|max:64',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'username.regex' => __('Please input correct username'),
|
'username.regex' => __('Please input correct username'),
|
||||||
@@ -129,6 +145,7 @@ class User extends Frontend
|
|||||||
'password' => __('Password'),
|
'password' => __('Password'),
|
||||||
'captcha' => __('captcha'),
|
'captcha' => __('captcha'),
|
||||||
'registerType' => __('Register type'),
|
'registerType' => __('Register type'),
|
||||||
|
'invite_code' => __('Invite code'),
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ if (!function_exists('get_controller_path')) {
|
|||||||
* 从 Request 或路由获取控制器路径(等价于 ThinkPHP controllerPath)
|
* 从 Request 或路由获取控制器路径(等价于 ThinkPHP controllerPath)
|
||||||
* 优先从 $request->controller(Webman 路由匹配时设置)解析,否则从 path 解析
|
* 优先从 $request->controller(Webman 路由匹配时设置)解析,否则从 path 解析
|
||||||
* @param \Webman\Http\Request|null $request
|
* @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
|
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
|
// admin/auth/adminLog
|
||||||
Route::get('/admin/auth/adminLog/index', [\app\admin\controller\auth\AdminLog::class, 'index']);
|
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
|
// admin/routine/config
|
||||||
Route::get('/admin/routine/config/index', [\app\admin\controller\routine\Config::class, 'index']);
|
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']);
|
Route::post('/admin/routine/config/edit', [\app\admin\controller\routine\Config::class, 'edit']);
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ class InstallData extends AbstractMigration
|
|||||||
$this->menuRule();
|
$this->menuRule();
|
||||||
$this->securityDataRecycle();
|
$this->securityDataRecycle();
|
||||||
$this->securitySensitiveData();
|
$this->securitySensitiveData();
|
||||||
$this->user();
|
|
||||||
$this->userGroup();
|
|
||||||
$this->userRule();
|
$this->userRule();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,245 +454,6 @@ class InstallData extends AbstractMigration
|
|||||||
'updatetime' => $this->nowTime,
|
'updatetime' => $this->nowTime,
|
||||||
'createtime' => $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',
|
'id' => '44',
|
||||||
'type' => 'menu_dir',
|
'type' => 'menu_dir',
|
||||||
@@ -1214,16 +973,6 @@ class InstallData extends AbstractMigration
|
|||||||
'updatetime' => $this->nowTime,
|
'updatetime' => $this->nowTime,
|
||||||
'createtime' => $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,
|
'id' => 6,
|
||||||
'name' => '数据回收规则',
|
'name' => '数据回收规则',
|
||||||
@@ -1257,18 +1006,6 @@ class InstallData extends AbstractMigration
|
|||||||
'updatetime' => $this->nowTime,
|
'updatetime' => $this->nowTime,
|
||||||
'createtime' => $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,
|
'id' => 3,
|
||||||
'name' => '管理员权限',
|
'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
|
public function userRule(): void
|
||||||
{
|
{
|
||||||
$table = $this->table('user_rule');
|
$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 {
|
export default {
|
||||||
'/': ['./frontend/${lang}/index.ts'],
|
'/': ['./frontend/${lang}/index.ts'],
|
||||||
[adminBaseRoutePath + '/moduleStore']: ['./backend/${lang}/module.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'],
|
[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