Skip to content

Commit

Permalink
Merge pull request eee555#67 from putianyi889/patch-52
Browse files Browse the repository at this point in the history
增加管理员修改录像属性的前后端接口
  • Loading branch information
eee555 authored Jul 23, 2024
2 parents 1c12230 + 8943ed6 commit b9ae660
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 51 deletions.
18 changes: 9 additions & 9 deletions back_end/saolei/userprofile/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,21 +284,21 @@ def judge_captcha(captchaStr, captchaHashkey):
CaptchaStore.objects.filter(hashkey=captchaHashkey).delete()
return False


get_userProfile_fields = ["id", "userms__designators", "userms__video_num_limit", "username", "first_name", "last_name", "email", "realname", "signature", "country", "left_realname_n", "left_avatar_n", "left_signature_n", "is_banned"]

# 管理员使用的操作接口,调用方式见前端的StaffView.vue
get_userProfile_fields = ["id", "userms__designators", "userms__video_num_limit", "username", "first_name", "last_name", "email", "realname", "signature", "country", "left_realname_n", "left_avatar_n", "left_signature_n", "is_banned"] # 可获取的域列表
def get_userProfile(request):
if request.method != 'GET':
return HttpResponseBadRequest()
if request.user.is_staff:
list = UserProfile.objects.filter(id=request.GET["id"]).values(*get_userProfile_fields)
if len(list) == 0:
userlist = UserProfile.objects.filter(id=request.GET["id"]).values(*get_userProfile_fields)
if not userlist:
return HttpResponseNotFound()
return JsonResponse(list[0])
return JsonResponse(userlist[0])
else:
return HttpResponseForbidden()

set_userProfile_fields = ["id", "userms__designators", "userms__video_num_limit", "username", "first_name", "last_name", "email", "realname", "signature", "country", "left_realname_n", "left_avatar_n", "left_signature_n", "is_banned"]

# 管理员使用的操作接口,调用方式见前端的StaffView.vue
set_userProfile_fields = ["userms__designators", "userms__video_num_limit", "username", "first_name", "last_name", "email", "realname", "signature", "country", "left_realname_n", "left_avatar_n", "left_signature_n", "is_banned"] # 可修改的域列表
def set_userProfile(request):
if request.method == 'POST':
if not request.user.is_staff:
Expand All @@ -313,7 +313,7 @@ def set_userProfile(request):
if field == "is_banned" and user.is_superuser:
return HttpResponseForbidden() # 站长不可被封禁
value = request.POST.get("value")
logger.info(f'{request.user.id}(staff) changes {userid}.{field} from {getattr(user, field)} to {value}')
logger.info(f'{request.user.id}(staff) changes user{userid}.{field} from {getattr(user, field)} to {value}')
setattr(user, field, value)
user.save()
return HttpResponse()
Expand Down
2 changes: 2 additions & 0 deletions back_end/saolei/videomanager/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
path('news_queue/', views.news_queue, name='news_queue'),
path('approve/', views.approve, name='approve'),
path('freeze/', views.freeze, name='freeze'),
path('get/',views.get_videoModel),
path('set/',views.set_videoModel),
# path('download/', views.video_download, name='download'),

]
36 changes: 36 additions & 0 deletions back_end/saolei/videomanager/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ def video_download(request):
# 录像查询(无需登录)
# 按任何基础指标+难度+模式,排序,分页
# 每项的定义参见 front_end/src/views/VideoView.vue 的 request_videos 函数

@ratelimit(key='ip', rate='20/m')
def video_query(request):
if request.method == 'GET':
Expand Down Expand Up @@ -392,7 +393,42 @@ def freeze(request):
else:
return HttpResponseNotAllowed()

# 管理员使用的操作接口,调用方式见前端的StaffView.vue
get_videoModel_fields = ["player", "player__realname", "upload_time", "state", "software", "level", "mode", "timems", "bv", "bvs"] # 可获取的域列表
for name in [field.name for field in ExpandVideoModel._meta.get_fields()]:
get_videoModel_fields.append("video__" + name)

def get_videoModel(request):
if request.method != 'GET':
return HttpResponseBadRequest()
if request.user.is_staff:
videolist = VideoModel.objects.filter(id=request.GET["id"]).values(*get_videoModel_fields)
if not videolist:
return HttpResponseNotFound()
return JsonResponse(videolist[0])
else:
return HttpResponseForbidden()

set_videoModel_fields = ["player", "upload_time", "state"] # 可修改的域列表
def set_videoModel(request):
if request.method == 'POST':
if not request.user.is_staff:
return HttpResponseForbidden() # 非管理员不能使用该api
videoid = request.POST.get("id")
video = VideoModel.objects.get(id=videoid)
user = video.player
if user.is_staff and user != request.user:
return HttpResponseForbidden() # 不能修改除自己以外管理员的信息
field = request.POST.get("field")
if field not in set_videoModel_fields:
return HttpResponseForbidden() # 只能修改特定的域
value = request.POST.get("value")
logger.info(f'{request.user.id}(staff) changes video{videoid}.{field} from {getattr(video, field)} to {value}')
setattr(video, field, value)
video.save()
return HttpResponse()
else:
return HttpResponseBadRequest()



5 changes: 5 additions & 0 deletions front_end/src/i18n/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ export const en = {
action: {
getSoftware: 'fetch video data',
getUserProfile: 'fetch user data',
getVideoModel: 'fetch video data',
setUserProfile: 'modify user data',
setVideoModel: 'modify video data',
uploadFile: 'upload file',
videoQuery: 'fetch video data',
},
Expand Down Expand Up @@ -106,6 +108,9 @@ export const en = {
links: 'Links',
team: 'Team'
},
news: {
breakRecordTo: ' breaks their {mode} {level} {stat} record with ',
},
profile: {
changeAvatar: 'Click the image to change avatar',
realname: 'Name: ',
Expand Down
5 changes: 5 additions & 0 deletions front_end/src/i18n/locales/zh-cn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ export const zhCn = {
action: {
getSoftware: '获取录像信息',
getUserProfile: '查询用户',
getVideoModel: '查询录像',
setUserProfile: '修改用户',
setVideoModel: '修改录像',
uploadFile: '上传文件',
videoQuery: '查询录像',
},
Expand Down Expand Up @@ -107,6 +109,9 @@ export const zhCn = {
team: '团队',
groups: '官方QQ群'
},
news: {
breakRecordTo: '将{mode}{level}{stat}纪录刷新为',
},
profile: {
changeAvatar: '*点击图片修改头像',
realname: '姓名:',
Expand Down
16 changes: 0 additions & 16 deletions front_end/src/utils/common/structInterface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,22 +49,6 @@ export interface Record {
path_id: number,
}

export interface UserProfile {
userms__designators: Array<String>;
userms__video_num_limit: Number;
username: String;
first_name: String;
last_name: String;
email: String;
realname: String;
signature: String;
country: String;
is_banned: Boolean;
left_realname_n: Number;
left_avatar_n: Number;
left_signature_n: Number;
}

interface ExtendedVideoStat {
left: number,
right: number,
Expand Down
17 changes: 11 additions & 6 deletions front_end/src/views/HomeView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@
<el-tabs type="border-card" style=" min-height: 300px;">
<el-tab-pane label="雷界快讯" style="max-height: 300px; overflow: auto;user-select: none;">
<div v-for="news in news_queue">
{{ utc_to_local_format(news.time) }}<PlayerName class="name" :user_id="+news.player_id" :user_name="news.player">
</PlayerName>将{{ $t('common.mode.'+news.mode) }}模式{{ $t('common.level.'+news.level)
}}{{ $t('common.prop.'+news.index) }}记录刷新为
<PreviewNumber :id="news.video_id" :text="to_fixed_n(news.value, 3)"></PreviewNumber>
{{ news.delta == "新" ? "" : news.delta > 0 ? "↑" : "↓" }}{{ news.delta }}

<el-text style="margin-right: 5px">
{{ utc_to_local_format(news.time) }}
</el-text>
<PlayerName class="name" style="vertical-align: top;" :user_id="+news.player_id" :user_name="news.player" />
<el-text style="vertical-align: middle;">
{{ $t('news.breakRecordTo', {mode: $t('common.mode.'+news.mode), level: $t('common.level.'+news.level), stat: $t('common.prop.'+news.index)}) }}
</el-text>
<PreviewNumber :id="news.video_id" :text="to_fixed_n(news.value, 3)" />
<el-text style="margin-left: 5px; vertical-align: middle;">
{{ news.delta == "新" ? "" : news.delta > 0 ? "↑" : "↓" }}{{ news.delta }}
</el-text>
</div>
<!-- 2023年2月26日 11:45 周炎亮 将高级标准模式时间记录刷新为 91.52 ↑3.60-->
</el-tab-pane>
Expand Down
72 changes: 52 additions & 20 deletions front_end/src/views/StaffView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
</div>
<div>
域<el-select v-model="userfield">
<el-option v-for="field in descriptionitems" :value="field"></el-option>
<el-option v-for="field in userfieldlist" :value="field"></el-option>
</el-select>
</div>
<div>
Expand All @@ -16,42 +16,49 @@
<el-button @click="setUser(userid, userfield, uservalue)">修改</el-button>
</div>
<el-descriptions title="UserProfile">
<el-descriptions-item v-for="item in descriptionitems" :label="item">{{ userprofile[item] }}</el-descriptions-item>
<el-descriptions-item v-for="(value, field) in userprofile" :label="field">{{ value }}</el-descriptions-item>
</el-descriptions>
<el-divider />
<div>
录像ID
<el-input-number v-model="videoid" :controls="false" :min="0"></el-input-number>
<el-button @click="getVideo">查询</el-button>
<el-button @click="preview(videoid)">播放</el-button>
</div>
<div>
域<el-select v-model="videofield">
<el-option v-for="field in videofieldlist" :value="field"></el-option>
</el-select>
</div>
<div>
值<el-input v-model="videovalue"></el-input>
</div>
<div>
<el-button @click="setVideo(videoid, videofield, videovalue)">修改</el-button>
</div>
<el-descriptions title="VideoModel">
<el-descriptions-item v-for="(value, field) in videomodel" :label="field">{{ value }}</el-descriptions-item>
</el-descriptions>
</template>

<script lang="ts" setup>
// 管理员操作接口,通过'/staff'访问
import useCurrentInstance from '@/utils/common/useCurrentInstance';
import { generalNotification } from '@/utils/system/status';
import { UserProfile } from '@/utils/common/structInterface';
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { preview } from '@/utils/common/PlayerDialog';
const t = useI18n();
const { proxy } = useCurrentInstance();
const userid = ref(0);
const userfield = ref("");
const uservalue = ref("");
const descriptionitems = ["username", "first_name", "last_name", "email", "realname", "country", "is_banned", "left_realname_n", "left_avatar_n", "left_signature_n"]
const userprofile = ref<UserProfile>({
userms__designators: [],
userms__video_num_limit: 0,
username: "",
first_name: "",
last_name: "",
email: "",
realname: "",
signature: "",
country: "",
is_banned: false,
left_realname_n: 0,
left_avatar_n: 0,
left_signature_n: 0,
});
const userfieldlist = ["username", "first_name", "last_name", "email", "realname", "country", "is_banned", "left_realname_n", "left_avatar_n", "left_signature_n", "userms__video_num_limit"]; // 可以修改的域列表
const userprofile = ref({});
const getUser = () => {
proxy.$axios.get('userprofile/get', {params: {id: userid.value}}).then(
Expand All @@ -72,4 +79,29 @@ const setUser = (id: number, field: string, value: string) => {
)
}
const videoid = ref(0);
const videofield = ref("");
const videovalue = ref("");
const videofieldlist = ["player", "upload_time", "state"]; // 可以修改的域列表
const videomodel = ref({});
const getVideo = () => {
proxy.$axios.get('video/get', {params: {id: videoid.value}}).then(
function (response: any) {
videomodel.value = response.data;
}
).catch(error => {
generalNotification(t, error.response.status, t.t('common.action.getUserProfile'))
})
}
const setVideo = (id: number, field: string, value: string) => {
proxy.$axios.post('video/set/', {id: id, field: field, value: value}).then(
function (response: any) {
generalNotification(t, response.status, t.t('common.action.setUserProfile'));
getVideo();
}
)
}
</script>

0 comments on commit b9ae660

Please sign in to comment.