Merge commit '814a488801b328daf67f86c33ac422704303dceb' into pro

# Conflicts:
#	app/Http/Controllers/Api/SystemController.php
#	public/site/en/about.html
#	public/site/en/download.html
#	public/site/en/help.html
#	public/site/en/index.html
#	public/site/en/log.html
#	public/site/en/price.html
#	public/site/en/product.html
#	public/site/en/solutions.html
#	public/site/zh/about.html
#	public/site/zh/download.html
#	public/site/zh/help.html
#	public/site/zh/index.html
#	public/site/zh/log.html
#	public/site/zh/price.html
#	public/site/zh/product.html
#	public/site/zh/solutions.html
#	resources/mobile
This commit is contained in:
kuaifan 2024-10-21 14:14:45 +08:00
commit 2284788366
11 changed files with 406 additions and 57 deletions

View File

@ -78,17 +78,28 @@ class PublicController extends AbstractController
$key = trim(Request::input('key')); $key = trim(Request::input('key'));
$mac = trim(Request::input('mac')); $mac = trim(Request::input('mac'));
$time = intval(Request::input('time')); $time = intval(Request::input('time'));
$type = trim(Request::input('type'));
// //
$setting = Base::setting('checkinSetting'); $setting = Base::setting('checkinSetting');
if ($setting['open'] !== 'open') { if ($setting['open'] !== 'open') {
return 'function off'; return 'function off';
} }
if ($type === 'face') {
if (!in_array('face', $setting['modes'])) {
return 'mode off';
}
if ($key != $setting['face_key']) {
return 'key error';
}
} else {
if (!in_array('auto', $setting['modes'])) { if (!in_array('auto', $setting['modes'])) {
return 'mode off'; return 'mode off';
} }
if ($key != $setting['key']) { if ($key != $setting['key']) {
return 'key error'; return 'key error';
} }
}
if ($error = UserBot::checkinBotCheckin($mac, $time)) { if ($error = UserBot::checkinBotCheckin($mac, $time)) {
return $error; return $error;
} }

View File

@ -399,6 +399,7 @@ class SystemController extends AbstractController
'remindin', 'remindin',
'remindexceed', 'remindexceed',
'edit', 'edit',
'faceupload',
'modes', 'modes',
'key', 'key',
])) { ])) {
@ -407,6 +408,7 @@ class SystemController extends AbstractController
} }
if ($all['open'] === 'close') { if ($all['open'] === 'close') {
$all['key'] = md5(Base::generatePassword(32)); $all['key'] = md5(Base::generatePassword(32));
$all['face_key'] = md5(Base::generatePassword(32));
} else { } else {
$botUser = User::botGetOrCreate('check-in'); $botUser = User::botGetOrCreate('check-in');
if (!$botUser) { if (!$botUser) {
@ -414,7 +416,7 @@ class SystemController extends AbstractController
} }
} }
if ($all['modes']) { if ($all['modes']) {
$all['modes'] = array_intersect($all['modes'], ['auto', 'manual', 'location']); $all['modes'] = array_intersect($all['modes'], ['auto', 'manual', 'location', 'face']);
} }
$setting = Base::setting('checkinSetting', Base::newTrim($all)); $setting = Base::setting('checkinSetting', Base::newTrim($all));
} else { } else {
@ -425,8 +427,13 @@ class SystemController extends AbstractController
$setting['key'] = md5(Base::generatePassword(32)); $setting['key'] = md5(Base::generatePassword(32));
Base::setting('checkinSetting', $setting); Base::setting('checkinSetting', $setting);
} }
if (empty($setting['face_key'])) {
$setting['face_key'] = md5(Base::generatePassword(32));
Base::setting('checkinSetting', $setting);
}
// //
$setting['open'] = $setting['open'] ?: 'close'; $setting['open'] = $setting['open'] ?: 'close';
$setting['faceupload'] = $setting['faceupload'] ?: 'close';
$setting['time'] = $setting['time'] ? Base::json2array($setting['time']) : ['09:00', '18:00']; $setting['time'] = $setting['time'] ? Base::json2array($setting['time']) : ['09:00', '18:00'];
$setting['advance'] = intval($setting['advance']) ?: 120; $setting['advance'] = intval($setting['advance']) ?: 120;
$setting['delay'] = intval($setting['delay']) ?: 120; $setting['delay'] = intval($setting['delay']) ?: 120;

View File

@ -20,6 +20,7 @@ use App\Models\UmengAlias;
use App\Models\UserDelete; use App\Models\UserDelete;
use App\Models\UserTransfer; use App\Models\UserTransfer;
use App\Models\AbstractModel; use App\Models\AbstractModel;
use App\Models\UserCheckinFace;
use App\Models\UserCheckinMac; use App\Models\UserCheckinMac;
use App\Models\UserDepartment; use App\Models\UserDepartment;
use App\Models\WebSocketDialog; use App\Models\WebSocketDialog;
@ -775,6 +776,14 @@ class UsersController extends AbstractController
} }
return $user; return $user;
}); });
// user_face
$list->transform(function (User $user) use ($getCheckinMac) {
if ($getCheckinMac) {
$checkinFace = UserCheckinFace::query()->whereUserid($user->userid)->first();
$user->checkin_face = $checkinFace ? Base::fillUrl($checkinFace->faceimg) : '';
}
return $user;
});
} }
// //
return Base::retSuccess('success', $list); return Base::retSuccess('success', $list);
@ -795,6 +804,7 @@ class UsersController extends AbstractController
* - settemp 设为临时帐号 * - settemp 设为临时帐号
* - cleartemp 取消临时身份(取消临时帐号) * - cleartemp 取消临时身份(取消临时帐号)
* - checkin_macs 修改自动签到mac地址需要参数 checkin_macs * - checkin_macs 修改自动签到mac地址需要参数 checkin_macs
* - checkin_face 修改签到人脸图片(需要参数 checkin_face
* - department 修改部门(需要参数 department * - department 修改部门(需要参数 department
* - setdisable 设为离职(需要参数 disable_time、transfer_userid * - setdisable 设为离职(需要参数 disable_time、transfer_userid
* - cleardisable 取消离职 * - cleardisable 取消离职
@ -805,6 +815,7 @@ class UsersController extends AbstractController
* @apiParam {String} [nickname] 昵称 * @apiParam {String} [nickname] 昵称
* @apiParam {String} [profession] 职位 * @apiParam {String} [profession] 职位
* @apiParam {String} [checkin_macs] 自动签到mac地址 * @apiParam {String} [checkin_macs] 自动签到mac地址
* @apiParam {String} [checkin_face] 人脸图片地址
* @apiParam {String} [department] 部门 * @apiParam {String} [department] 部门
* @apiParam {String} [disable_time] 离职时间 * @apiParam {String} [disable_time] 离职时间
* @apiParam {String} [transfer_userid] 离职交接人 * @apiParam {String} [transfer_userid] 离职交接人
@ -869,6 +880,11 @@ class UsersController extends AbstractController
} }
return UserCheckinMac::saveMac($userInfo->userid, $array); return UserCheckinMac::saveMac($userInfo->userid, $array);
case 'checkin_face':
$faceimg = $data['checkin_face'] ? $data['checkin_face'] : '';
return UserCheckinFace::saveFace($userInfo->userid, $userInfo->nickname, $faceimg, "管理员上传");
case 'department': case 'department':
if (!is_array($data['department'])) { if (!is_array($data['department'])) {
$data['department'] = []; $data['department'] = [];
@ -1643,8 +1659,14 @@ class UsersController extends AbstractController
$user = User::auth(); $user = User::auth();
// //
$list = UserCheckinMac::whereUserid($user->userid)->orderBy('id')->get(); $list = UserCheckinMac::whereUserid($user->userid)->orderBy('id')->get();
$userface = UserCheckinFace::whereUserid($user->userid)->first();
$data = [
'list' => $list,
'faceimg' => $userface ? Base::fillUrl($userface->faceimg) : ''
];
// //
return Base::retSuccess('success', $list); return Base::retSuccess('success', $data);
} }
/** /**
@ -1669,11 +1691,19 @@ class UsersController extends AbstractController
if ($setting['open'] !== 'open') { if ($setting['open'] !== 'open') {
return Base::retError('此功能未开启,请联系管理员开启'); return Base::retError('此功能未开启,请联系管理员开启');
} }
if ($setting['edit'] !== 'open') { if ($setting['edit'] !== 'open' && $setting['faceupload'] !== 'open') {
return Base::retError('未开放修改权限,请联系管理员'); return Base::retError('未开放修改权限,请联系管理员');
} }
// //
$list = Request::input('list'); $list = Request::input('list');
$faceimg = Request::input('faceimg');
// 默认返回值,使用用户传递数据
$data = [
'list' => $list,
'faceimg' => $faceimg
];
// 当mac允许修改
if ($setting['edit' === 'open']) {
$array = []; $array = [];
if (empty($list) || !is_array($list)) { if (empty($list) || !is_array($list)) {
return Base::retError('参数错误'); return Base::retError('参数错误');
@ -1691,8 +1721,23 @@ class UsersController extends AbstractController
if (count($array) > 3) { if (count($array) > 3) {
return Base::retError('最多只能添加3个MAC地址'); return Base::retError('最多只能添加3个MAC地址');
} }
// $saveMacRes = UserCheckinMac::saveMac($user->userid, $array);
return UserCheckinMac::saveMac($user->userid, $array); $data['list'] = $saveMacRes['data'];
} else {
$list = UserCheckinMac::whereUserid($user->userid)->orderBy('id')->get();
$data['list'] = $list;
}
// 当图片允许修改
if ($setting['faceupload'] === 'open') {
UserCheckinFace::saveFace($user->userid, $user->nickname(), $faceimg, "用户上传");
} else {
$userface = UserCheckinFace::whereUserid($user->userid)->first();
$data['faceimg'] = $userface;
}
return Base::retSuccess('修改成功', $data);
} }
/** /**

View File

@ -234,6 +234,19 @@ class UserBot extends AbstractModel
'remark' => '手动签到', 'remark' => '手动签到',
]; ];
} }
} elseif (Base::leftExists($mac, "checkin-", true)) {
$mac = Base::leftDelete($mac, "checkin-", true);
if ($UserInfo = User::whereUserid($mac)->whereBot(0)->first()) {
$array = [
'userid' => $UserInfo->userid,
'mac' => '00:00:00:00:00:00',
'date' => $nowDate,
];
$checkins[] = [
'userid' => $UserInfo->userid,
'remark' => '考勤机',
];
}
} }
if ($array) { if ($array) {
$record = UserCheckinRecord::where($array)->first(); $record = UserCheckinRecord::where($array)->first();

View File

@ -0,0 +1,103 @@
<?php
namespace App\Models;
use App\Exceptions\ApiException;
use App\Module\Base;
use App\Module\Ihttp;
/**
* App\Models\UserCheckinFace
*
* @property int $id
* @property int|null $userid 会员id
* @property string|null $faceimg 人脸图片
* @property int|null $status 状态
* @property string|null $remark 备注
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder|UserCheckinFace newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserCheckinFace newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserCheckinFace query()
* @method static \Illuminate\Database\Eloquent\Builder|UserCheckinFace whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserCheckinFace whereFaceimg($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserCheckinFace whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserCheckinFace whereRemark($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserCheckinFace whereStatus($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserCheckinFace whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserCheckinFace whereUserid($value)
* @mixin \Eloquent
*/
class UserCheckinFace extends AbstractModel
{
public static function saveFace($userid, $nickname, $faceimg, $remark='')
{
// 取上传图片的URL
$faceimg = Base::unFillUrl($faceimg);
$record = "";
if ($faceimg != '') {
$faceFile = public_path($faceimg);
$record = base64_encode(file_get_contents($faceFile));
}
$url = 'http://' . env('APP_IPPR') . '.55' . ":7788/user";
$data = [
'name' => $nickname,
'enrollid' => $userid,
'admin' => 0,
'backupnum' => 50,
];
if ($record != '') {
$data['record'] = $record;
}
$res = Ihttp::ihttp_post($url, json_encode($data), 15);
if($res['data'] && $data = json_decode($res['data'])){
if($data->ret != 1 && $data->msg){
throw new ApiException($data->msg);
}
}
return AbstractModel::transaction(function() use ($userid, $faceimg, $remark) {
$checkinFace = self::query()->whereUserid($userid)->first();
if ($checkinFace) {
self::updateData(['id' => $checkinFace->id], [
'faceimg' => $faceimg,
'status' => 1,
'remark' => $remark
]);
} else {
$checkinFace = new UserCheckinFace();
$checkinFace->faceimg = $faceimg;
$checkinFace->userid = $userid;
$checkinFace->remark = $remark;
$checkinFace->save();
}
if ($faceimg == '') {
$res = UserCheckinFace::deleteDeviceUser($userid);
if ($res) {
return $res;
}
}
return Base::retSuccess('设置成功');
});
}
public static function deleteDeviceUser($userid) {
$url = 'http://' . env('APP_IPPR') . '.55' . ":7788/user/delete";
$data = [
'enrollid' => $userid,
'backupnum' => 50, // 13 删除整个用户 50 删除图片
];
$res = Ihttp::ihttp_post($url, json_encode($data));
if($res['data'] && $data = json_decode($res['data'])){
if($data->ret != 1 && $data->msg){
throw new ApiException($data->msg);
// return Base::retError($data->msg);
}
}
}
}

View File

@ -0,0 +1,38 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUserCheckinFacesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
if (Schema::hasTable('user_checkin_faces'))
return;
Schema::create('user_checkin_faces', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('userid')->nullable()->default(0)->comment('会员id');
$table->string('faceimg')->nullable()->default('')->comment('人脸图片');
$table->integer('status')->nullable()->default(0)->comment('状态');
$table->string('remark',100)->nullable()->default('')->comment('备注');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('user_checkin_faces');
}
}

View File

@ -193,6 +193,27 @@ services:
depends_on: depends_on:
- mariadb - mariadb
restart: unless-stopped restart: unless-stopped
face:
container_name: "dootask-face-${APP_ID}"
image: "hitosea2020/dooface:0.0.1"
ports:
- "7788:7788"
environment:
TZ: "${TIMEZONE:-PRC}"
STORAGE: mysql
MYSQL_HOST: "${DB_HOST}"
MYSQL_PORT: "${DB_PORT}"
MYSQL_USERNAME: "${DB_USERNAME}"
MYSQL_PASSWORD: "${DB_PASSWORD}"
MYSQL_DB_NAME: "${DB_DATABASE}"
DB_PREFIX: "${DB_PREFIX}"
REPORT_API: "http://${APP_IPPR}.3:80/api/public/checkin/report"
depends_on:
- mariadb
networks:
extnetwork:
ipv4_address: "${APP_IPPR}.55"
restart: unless-stopped
networks: networks:
extnetwork: extnetwork:

View File

@ -237,6 +237,34 @@
</div> </div>
</Modal> </Modal>
<!--修改Face-->
<Modal
v-model="checkinFaceEditShow"
:title="$L('修改签到人脸图片')">
<Form :model="checkinMacEditData" label-width="auto" @submit.native.prevent>
<Alert type="error" style="margin-bottom:18px">{{$L(`正在进行帐号【ID:${checkinFaceEditData.userid}${checkinFaceEditData.nickname}】人脸图片修改。`)}}</Alert>
<Row class="team-department-checkin-item">
<Col span="12">{{$L('人脸图片')}}</Col>
<Col span="12"></Col>
</Row>
<Row class="team-department-checkin-item">
<Col span="12">
<ImgUpload v-model="checkinFaceEditData.faceimg" :num="1" :width="512" :height="512" :whcut="1"></ImgUpload>
<span class="form-tip">{{$L('建议尺寸200x200')}}</span>
</Col>
<Col span="12">
<!-- <Input v-model="item.remark" :maxlength="100" :placeholder="$L('备注')"/> -->
</Col>
</Row>
</Form>
<div slot="footer" class="adaption">
<Button type="default" @click="checkinFaceEditShow=false">{{$L('取消')}}</Button>
<Button type="primary" :loading="checkinFaceEditLoading > 0" @click="operationUser(checkinFaceEditData, true)">{{$L('确定修改')}}</Button>
</div>
</Modal>
<!--修改部门--> <!--修改部门-->
<Modal <Modal
v-model="departmentEditShow" v-model="departmentEditShow"
@ -300,10 +328,11 @@
<script> <script>
import UserSelect from "../../../components/UserSelect.vue"; import UserSelect from "../../../components/UserSelect.vue";
import UserAvatarTip from "../../../components/UserAvatar/tip.vue"; import UserAvatarTip from "../../../components/UserAvatar/tip.vue";
import ImgUpload from "../../../components/ImgUpload";
export default { export default {
name: "TeamManagement", name: "TeamManagement",
components: {UserAvatarTip, UserSelect}, components: {UserAvatarTip, UserSelect, ImgUpload},
props: { props: {
checkinMac: { checkinMac: {
type: Boolean, type: Boolean,
@ -591,6 +620,12 @@ export default {
command: 'checkin_mac', command: 'checkin_mac',
}, },
}, [h('div', this.$L('修改MAC'))])) }, [h('div', this.$L('修改MAC'))]))
dropdownItems.push(h('EDropdownItem', {
props: {
command: 'checkin_face',
},
}, [h('div', this.$L('修改人脸图片'))]))
} }
dropdownItems.push(h('EDropdownItem', { dropdownItems.push(h('EDropdownItem', {
@ -671,6 +706,10 @@ export default {
checkinMacEditLoading: 0, checkinMacEditLoading: 0,
checkinMacEditData: {}, checkinMacEditData: {},
checkinFaceEditShow: false,
checkinFaceEditLoading: 0,
checkinFaceEditData: {},
departmentEditShow: false, departmentEditShow: false,
departmentEditLoading: 0, departmentEditLoading: 0,
departmentEditData: {}, departmentEditData: {},
@ -753,12 +792,21 @@ export default {
created() { created() {
if (this.checkinMac) { if (this.checkinMac) {
this.columns.splice(5, 0, { this.columns.splice(5, 0, {
title: this.$L('MAC地址'), title: this.$L('设备情况'),
key: 'checkin_mac', key: 'checkin_mac',
minWidth: 80, minWidth: 80,
render: (h, {row}) => { render: (h, {row}) => {
let checkin_macs = $A.cloneJSON(row.checkin_macs || []) let checkin_macs = $A.cloneJSON(row.checkin_macs || [])
let checkin_face = $A.cloneJSON(row.checkin_face || '')
const tmp = []
const checkin_face_desc = checkin_face ? "已上传(人脸)" : "未上传(人脸)"
if (checkin_macs.length === 0) { if (checkin_macs.length === 0) {
if (checkin_face){
tmp.push(h('AutoTip', checkin_face_desc))
return h('div', {
class: 'team-table-department-warp'
}, tmp);
}
return h('div', '-'); return h('div', '-');
} else { } else {
const desc = (item) => { const desc = (item) => {
@ -767,22 +815,26 @@ export default {
} }
return item.mac return item.mac
} }
const tmp = [] const checkin_devices_desc = []
tmp.push(h('AutoTip', desc(checkin_macs[0]))) tmp.push(h('AutoTip', desc(checkin_macs[0])))
if (checkin_macs.length > 1) { if (checkin_macs.length > 1) {
checkin_macs = checkin_macs.splice(1) checkin_macs = checkin_macs.splice(1)
checkin_devices_desc.push(...checkin_macs.map(item => {
return desc(item)
}))
if (checkin_face) {
checkin_devices_desc.push(checkin_face_desc)
}
tmp.push(h('ETooltip', [ tmp.push(h('ETooltip', [
h('div', { h('div', {
slot: 'content', slot: 'content',
domProps: { domProps: {
innerHTML: checkin_macs.map(item => { innerHTML: checkin_devices_desc.join("<br/>")
return desc(item)
}).join("<br/>")
} }
}), }),
h('div', { h('div', {
class: 'department-tag-num' class: 'department-tag-num'
}, ` +${checkin_macs.length}`) }, ` +${checkin_devices_desc.length}`)
])) ]))
} }
return h('div', { return h('div', {
@ -955,6 +1007,16 @@ export default {
} }
this.checkinMacEditShow = true; this.checkinMacEditShow = true;
break; break;
case 'checkin_face':
this.checkinFaceEditData = {
type: 'checkin_face',
userid: row.userid,
nickname: row.nickname,
faceimg: row.checkin_face
};
this.checkinFaceEditShow = true;
break;
case 'department': case 'department':
let departments = [] let departments = []
@ -1026,6 +1088,14 @@ export default {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (data.type == 'checkin_macs') { if (data.type == 'checkin_macs') {
this.checkinMacEditLoading++; this.checkinMacEditLoading++;
} else if (data.type == 'checkin_face') {
this.checkinFaceEditLoading++;
data = {
type: data.type,
userid: data.userid,
nickname: data.nickname,
checkin_face: data.faceimg[0] ? data.faceimg[0].url : ''
}
} else if (data.type == 'department') { } else if (data.type == 'department') {
this.departmentEditLoading++; this.departmentEditLoading++;
} else if (data.type == 'setdisable') { } else if (data.type == 'setdisable') {
@ -1042,6 +1112,8 @@ export default {
resolve() resolve()
if (data.type == 'checkin_macs') { if (data.type == 'checkin_macs') {
this.checkinMacEditShow = false; this.checkinMacEditShow = false;
} else if (data.type == 'checkin_face') {
this.checkinFaceEditShow = false;
} else if (data.type == 'department') { } else if (data.type == 'department') {
this.departmentEditShow = false; this.departmentEditShow = false;
} else if (data.type == 'setdisable') { } else if (data.type == 'setdisable') {
@ -1056,6 +1128,8 @@ export default {
}).finally(_ => { }).finally(_ => {
if (data.type == 'checkin_macs') { if (data.type == 'checkin_macs') {
this.checkinMacEditLoading--; this.checkinMacEditLoading--;
} else if (data.type == 'checkin_face') {
this.checkinFaceEditLoading--;
} else if (data.type == 'department') { } else if (data.type == 'department') {
this.departmentEditLoading--; this.departmentEditLoading--;
} else if (data.type == 'setdisable') { } else if (data.type == 'setdisable') {

View File

@ -22,6 +22,8 @@
{{$L('设备连接上指定路由器WiFi后自动签到。')}} {{$L('设备连接上指定路由器WiFi后自动签到。')}}
</Alert> </Alert>
<div class="setting-checkin-row"> <div class="setting-checkin-row">
<Tabs v-model="checkinTabs" style="margin: 0;">
<TabPane :label="$L('设备MAC地址')" name="mac">
<Row class="setting-template"> <Row class="setting-template">
<Col span="12">{{$L('设备MAC地址')}}</Col> <Col span="12">{{$L('设备MAC地址')}}</Col>
<Col span="12">{{$L('备注')}}</Col> <Col span="12">{{$L('备注')}}</Col>
@ -39,8 +41,28 @@
<Input v-model="item.remark" :maxlength="100" :placeholder="$L('备注')"/> <Input v-model="item.remark" :maxlength="100" :placeholder="$L('备注')"/>
</Col> </Col>
</Row> </Row>
</div>
<Button type="default" icon="md-add" @click="addDatum">{{$L('添加设备')}}</Button> <Button type="default" icon="md-add" @click="addDatum">{{$L('添加设备')}}</Button>
</TabPane>
<TabPane :label="$L('人脸图片')" name="receive">
<div class="setting-checkin-row">
<Row class="setting-template">
<Col span="12">{{$L('人脸图片')}}</Col>
<Col span="12"></Col>
</Row>
<Row class="setting-template">
<Col span="12">
<ImgUpload v-model="faceimgs" :num="1" :width="512" :height="512" :whcut="1"></ImgUpload>
<span class="form-tip">{{$L('建议尺寸200x200')}}</span>
</Col>
</Row>
</div>
</TabPane>
</Tabs>
</div>
</Form> </Form>
<div class="setting-footer"> <div class="setting-footer">
<Button :loading="loadIng > 0" type="primary" @click="submitForm">{{$L('提交')}}</Button> <Button :loading="loadIng > 0" type="primary" @click="submitForm">{{$L('提交')}}</Button>
@ -59,9 +81,10 @@
<script> <script>
import CheckinCalendar from "../components/CheckinCalendar"; import CheckinCalendar from "../components/CheckinCalendar";
import ImgUpload from "../../../components/ImgUpload";
export default { export default {
name: "ManageCheckin", name: "ManageCheckin",
components: {CheckinCalendar}, components: {CheckinCalendar, ImgUpload},
data() { data() {
return { return {
@ -69,10 +92,13 @@ export default {
formData: [], formData: [],
faceimgs: [],
nullDatum: { nullDatum: {
'mac': '', 'mac': '',
'remark': '', 'remark': '',
}, },
checkinTabs: "mac",
latelyLoad: 0, latelyLoad: 0,
latelyData: [], latelyData: [],
@ -104,7 +130,8 @@ export default {
this.$store.dispatch("call", { this.$store.dispatch("call", {
url: 'users/checkin/get', url: 'users/checkin/get',
}).then(({data}) => { }).then(({data}) => {
this.formData = data.length > 0 ? data : [$A.cloneJSON(this.nullDatum)]; this.formData = data.list.length > 0 ? data.list : [$A.cloneJSON(this.nullDatum)];
this.faceimgs = data.faceimg
this.formData_bak = $A.cloneJSON(this.formData); this.formData_bak = $A.cloneJSON(this.formData);
}).catch(({msg}) => { }).catch(({msg}) => {
$A.modalError(msg); $A.modalError(msg);
@ -124,14 +151,16 @@ export default {
remark: item.remark.trim() remark: item.remark.trim()
} }
}); });
const faceimg = this.faceimgs ? this.faceimgs[0].url : ''
// //
this.loadIng++; this.loadIng++;
this.$store.dispatch("call", { this.$store.dispatch("call", {
url: 'users/checkin/save', url: 'users/checkin/save',
data: {list}, data: {list, faceimg},
method: 'post', method: 'post',
}).then(({data}) => { }).then(({data}) => {
this.formData = data; this.formData = data.list;
this.faceimgs = data.faceimg
this.formData_bak = $A.cloneJSON(this.formData); this.formData_bak = $A.cloneJSON(this.formData);
$A.messageSuccess('修改成功'); $A.messageSuccess('修改成功');
}).catch(({msg}) => { }).catch(({msg}) => {

View File

@ -56,15 +56,22 @@
<Radio label="close">{{ $L('禁止') }}</Radio> <Radio label="close">{{ $L('禁止') }}</Radio>
</RadioGroup> </RadioGroup>
<div class="form-tip">{{$L('允许成员自己修改MAC地址')}}</div> <div class="form-tip">{{$L('允许成员自己修改MAC地址')}}</div>
<RadioGroup v-model="formData.faceupload">
<Radio label="open">{{ $L('允许') }}</Radio>
<Radio label="close">{{ $L('禁止') }}</Radio>
</RadioGroup>
<div class="form-tip">{{$L('允许成员自己上传人脸图片')}}</div>
</FormItem> </FormItem>
<FormItem :label="$L('签到方式')" prop="modes"> <FormItem :label="$L('签到方式')" prop="modes">
<CheckboxGroup v-model="formData.modes"> <CheckboxGroup v-model="formData.modes">
<Checkbox label="auto">{{$L('自动签到')}}</Checkbox> <Checkbox label="auto">{{$L('自动签到')}}</Checkbox>
<Checkbox label="manual">{{$L('手动签到')}}</Checkbox> <Checkbox label="manual">{{$L('手动签到')}}</Checkbox>
<Checkbox label="face">{{$L('人脸签到')}}</Checkbox>
<Checkbox v-if="false" label="location">{{$L('定位签到')}}</Checkbox> <Checkbox v-if="false" label="location">{{$L('定位签到')}}</Checkbox>
</CheckboxGroup> </CheckboxGroup>
<div v-if="formData.modes.includes('auto')" class="form-tip">{{$L('自动签到')}}: {{$L('详情看下文安装说明')}}</div> <div v-if="formData.modes.includes('auto')" class="form-tip">{{$L('自动签到')}}: {{$L('详情看下文安装说明')}}</div>
<div v-if="formData.modes.includes('manual')" class="form-tip">{{$L('手动签到')}}: {{$L('通过在签到打卡机器人发送指令签到')}}</div> <div v-if="formData.modes.includes('manual')" class="form-tip">{{$L('手动签到')}}: {{$L('通过在签到打卡机器人发送指令签到')}}</div>
<div v-if="formData.modes.includes('face')" class="form-tip">{{$L('人脸签到')}}: {{$L('')}}</div>
<div v-if="formData.modes.includes('location')" class="form-tip">{{$L('定位签到')}}: {{$L('通过在签到打卡机器人发送位置签到')}}</div> <div v-if="formData.modes.includes('location')" class="form-tip">{{$L('定位签到')}}: {{$L('通过在签到打卡机器人发送位置签到')}}</div>
</FormItem> </FormItem>
</template> </template>
@ -119,6 +126,7 @@ export default {
formData: { formData: {
open: '', open: '',
faceupload: '',
edit: '', edit: '',
cmd: '', cmd: '',
modes: [], modes: [],

View File

@ -24,7 +24,7 @@ export default {
await $A.IDBRemove("cacheVersion") await $A.IDBRemove("cacheVersion")
} }
const cacheVersion = await $A.IDBString("cacheVersion") const cacheVersion = await $A.IDBString("cacheVersion")
if (cacheVersion !== state.cacheVersion) { if (cacheVersion && cacheVersion !== state.cacheVersion) {
await dispatch("handleClearCache") await dispatch("handleClearCache")
} else { } else {
await dispatch("handleReadCache") await dispatch("handleReadCache")