diff --git a/fir_admin/src/api/app.js b/fir_admin/src/api/app.js
index 7606992..91d9ddb 100644
--- a/fir_admin/src/api/app.js
+++ b/fir_admin/src/api/app.js
@@ -2,7 +2,7 @@ import request from '@/utils/request'
export function getAppInfos(query) {
return request({
- url: '/appinfo',
+ url: '/app/info',
method: 'get',
params: query
})
@@ -10,7 +10,23 @@ export function getAppInfos(query) {
export function updateAppInfo(data) {
return request({
- url: '/appinfo',
+ url: '/app/info',
+ method: 'put',
+ data
+ })
+}
+
+export function getAppReleaseInfos(query) {
+ return request({
+ url: '/app/release/info',
+ method: 'get',
+ params: query
+ })
+}
+
+export function updateReleaseAppInfo(data) {
+ return request({
+ url: '/app/release/info',
method: 'put',
data
})
diff --git a/fir_admin/src/router/index.js b/fir_admin/src/router/index.js
index 6b019b7..8a30e93 100644
--- a/fir_admin/src/router/index.js
+++ b/fir_admin/src/router/index.js
@@ -102,6 +102,20 @@ export const constantRoutes = [
name: 'app_info_edit',
meta: { title: '编辑信息', noCache: true, activeMenu: '/apps/list' },
hidden: true
+ },
+ {
+ path: 'release/:app_id(\\d+)/list',
+ name: 'app_release_info_list',
+ component: () => import('@/views/appinfos/AppReleaseList'),
+ meta: { title: '版本记录', noCache: true, activeMenu: '/apps/list' },
+ hidden: true
+ },
+ {
+ path: 'release/:app_id(\\d+)/edit/:id(\\d+)',
+ name: 'app_release_info_edit',
+ component: () => import('@/views/appinfos/AppReleaseDetail'),
+ meta: { title: '版本记录', noCache: true, activeMenu: '/apps/list' },
+ hidden: true
}
]
},
diff --git a/fir_admin/src/views/appinfos/AppDetail.vue b/fir_admin/src/views/appinfos/AppDetail.vue
index 51de4c6..16c3942 100644
--- a/fir_admin/src/views/appinfos/AppDetail.vue
+++ b/fir_admin/src/views/appinfos/AppDetail.vue
@@ -297,9 +297,3 @@ export default {
}
-
-
diff --git a/fir_admin/src/views/appinfos/AppReleaseDetail.vue b/fir_admin/src/views/appinfos/AppReleaseDetail.vue
new file mode 100644
index 0000000..e829c2d
--- /dev/null
+++ b/fir_admin/src/views/appinfos/AppReleaseDetail.vue
@@ -0,0 +1,195 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 修改
+
+ 取消
+ 保存修改
+
+
+
+
+
+
+
diff --git a/fir_admin/src/views/appinfos/AppReleaseList.vue b/fir_admin/src/views/appinfos/AppReleaseList.vue
new file mode 100644
index 0000000..cbcf6b5
--- /dev/null
+++ b/fir_admin/src/views/appinfos/AppReleaseList.vue
@@ -0,0 +1,167 @@
+
+
+
+
+
+
+
+
+ Search
+
+
+
+
+
+ {{ scope.row.id }}
+
+
+
+
+
+
+
+
+
+
+ {{ scope.row.release_id }}
+
+
+
+
+ {{ scope.row.binary_url }}
+
+
+
+
+ {{ scope.row.changelog }}
+
+
+
+
+ {{ scope.row.is_master }}
+
+
+
+
+ {{ scope.row |appStatusNameFilter }}
+
+
+
+
+ {{ scope.row.binary_size }}
+
+
+
+
+
+
+ {{ scope.row.created_time|formatTime }}
+
+
+
+
+
+
+
+ 查看编辑
+
+
+
+
+
+
+
+
+
+
+
diff --git a/fir_admin/src/views/appinfos/list.vue b/fir_admin/src/views/appinfos/list.vue
index e775a38..5f1e41d 100644
--- a/fir_admin/src/views/appinfos/list.vue
+++ b/fir_admin/src/views/appinfos/list.vue
@@ -33,7 +33,7 @@
{{ scope.row.id }}
-
+
@@ -76,6 +76,18 @@
{{ scope.row.count_hits }}
+
+
+ {{ scope.row.master_release.binary_size }}
+
+
+
+
+
+ {{ scope.row.release_count }}
+
+
+
{{ scope.row |appStatusNameFilter }}
@@ -96,13 +108,16 @@
-
+
-
- 编辑
+
+ 查看编辑
+
+ 删除
+
diff --git a/fir_admin/src/views/userinfos/UserDetail.vue b/fir_admin/src/views/userinfos/UserDetail.vue
index 3099a6c..3200bab 100644
--- a/fir_admin/src/views/userinfos/UserDetail.vue
+++ b/fir_admin/src/views/userinfos/UserDetail.vue
@@ -50,6 +50,18 @@
+
+
+
+
+
+
+
+
+ 用户需要先提交认证信息,才可以进行认证修改
+
+
+
@@ -305,6 +317,7 @@ export default {
source_uri: [{ validator: validateSourceUri, trigger: 'blur' }]
},
is_edit: false,
+ certification_status_choices: []
}
},
computed: {
@@ -320,6 +333,7 @@ export default {
getUserInfos({ id: id }).then(response => {
if (response.data.length === 1) {
this.postForm = response.data[0]
+ this.certification_status_choices = this.postForm.certification_status_choices
}
}).catch(err => {
console.log(err)
diff --git a/fir_admin/src/views/userinfos/list.vue b/fir_admin/src/views/userinfos/list.vue
index 2b36146..ad9a9dc 100644
--- a/fir_admin/src/views/userinfos/list.vue
+++ b/fir_admin/src/views/userinfos/list.vue
@@ -6,7 +6,7 @@
-
+
@@ -79,7 +79,7 @@
- {{ scope.row.certification| certLableFilter }}
+ {{ scope.row| certLableFilter }}
@@ -94,8 +94,8 @@
-
- 编辑
+
+ 查看编辑
@@ -111,13 +111,6 @@ import { getUserInfos } from '@/api/user'
import Pagination from '@/components/Pagination' // secondary package based on el-pagination
import waves from '@/directive/waves' // waves directive
-const searchCertficationOptions = [
- { key: '-1', display_name: '未认证' },
- { key: '0', display_name: '认证中' },
- { key: '1', display_name: '认证成功' },
- { key: '2', display_name: '认证失败' }
-]
-
const sortOptions = [
{ label: '注册时间 Ascending', key: 'date_joined' },
{ label: '注册时间 Descending', key: '-date_joined' },
@@ -149,10 +142,10 @@ export default {
}
return statusMap[status]
},
- certLableFilter(status) {
- for (const v of searchCertficationOptions) {
- if (v.key === status.toString()) {
- return v.display_name
+ certLableFilter(row) {
+ for (const v of row.certification_status_choices) {
+ if (v.id === row.certification) {
+ return v.name
}
}
}
@@ -172,7 +165,7 @@ export default {
mobile: undefined
},
sortOptions,
- searchCertficationOptions
+ certification_status_choices: []
}
},
created() {
@@ -188,6 +181,9 @@ export default {
getUserInfos(this.listQuery).then(response => {
this.list = response.data
this.total = response.total
+ if (this.list && this.list.length > 0) {
+ this.certification_status_choices = this.list[0].certification_status_choices
+ }
this.listLoading = false
})
}
diff --git a/fir_client/src/components/user/FirUserProfileCertification.vue b/fir_client/src/components/user/FirUserProfileCertification.vue
index 3e4a1e4..405c6f5 100644
--- a/fir_client/src/components/user/FirUserProfileCertification.vue
+++ b/fir_client/src/components/user/FirUserProfileCertification.vue
@@ -76,7 +76,7 @@
-
diff --git a/fir_ser/admin/urls.py b/fir_ser/admin/urls.py
index 5374988..6cfab6e 100644
--- a/fir_ser/admin/urls.py
+++ b/fir_ser/admin/urls.py
@@ -16,7 +16,7 @@ Including another URLconf
from django.urls import re_path
from admin.views.login import LoginView, LoginUserView
from admin.views.user import UserInfoView
-from admin.views.app import AppInfoView
+from admin.views.app import AppInfoView, AppReleaseInfoView
urlpatterns = [
# path("",include(router.urls)),
@@ -25,6 +25,7 @@ urlpatterns = [
re_path("^login", LoginView.as_view()),
re_path("^user/info", LoginUserView.as_view()),
re_path("^userinfo", UserInfoView.as_view()),
- re_path("^appinfo", AppInfoView.as_view()),
+ re_path("^app/info", AppInfoView.as_view()),
+ re_path("^app/release/info", AppReleaseInfoView.as_view()),
]
diff --git a/fir_ser/admin/views/app.py b/fir_ser/admin/views/app.py
index 87aef05..d7ee93e 100644
--- a/fir_ser/admin/views/app.py
+++ b/fir_ser/admin/views/app.py
@@ -55,14 +55,14 @@ class AppInfoView(APIView):
def put(self, request):
res = BaseResponse()
data = request.data
- id = data.get("id", None)
- if not id:
+ pk = data.get("id", None)
+ if not pk:
res.code = 1003
res.msg = "参数错误"
return Response(res.dict)
- app_obj = Apps.objects.filter(id=id).first()
+ app_obj = Apps.objects.filter(pk=pk).first()
if app_obj:
- data['pk'] = id
+ data['pk'] = pk
serializer_obj = AdminAppsSerializer(app_obj, data=data, partial=True)
if serializer_obj.is_valid():
serializer_obj.save()
@@ -73,6 +73,16 @@ class AppInfoView(APIView):
res.msg = "数据校验失败"
return Response(res.dict)
+ def delete(self, request):
+ res = BaseResponse()
+ data = request.data
+ pk = data.get("id", None)
+ if not pk:
+ res.code = 1003
+ res.msg = "参数错误"
+ Apps.delete()
+ return Response(res.dict)
+
class AppReleaseInfoView(APIView):
authentication_classes = [AdminTokenAuthentication, ]
@@ -80,12 +90,16 @@ class AppReleaseInfoView(APIView):
def get(self, request):
res = BaseResponse()
filter_data = {}
- filter_fields = ["id", "release_id"]
+ filter_fields = ["id", "release_id", "app_id"]
for filed in filter_fields:
f_value = request.query_params.get(filed, None)
if f_value:
filter_data[filed] = f_value
sort = request.query_params.get("sort", "-created_time")
+ if not filter_data.get('app_id', None):
+ res.code = 1003
+ res.msg = "参数错误"
+ return Response(res.dict)
page_obj = AppsPageNumber()
obj_list = AppReleaseInfo.objects.filter(**filter_data).order_by(sort)
page_serializer = page_obj.paginate_queryset(queryset=obj_list, request=request,
@@ -98,19 +112,20 @@ class AppReleaseInfoView(APIView):
def put(self, request):
res = BaseResponse()
data = request.data
- id = data.get("id", None)
- if not id:
+ pk = data.get("id", None)
+ app_id = data.get("app_id", None)
+ if not pk or not app_id:
res.code = 1003
res.msg = "参数错误"
return Response(res.dict)
- app_obj = Apps.objects.filter(id=id).first()
+ app_obj = AppReleaseInfo.objects.filter(pk=pk, app_id=app_id).first()
if app_obj:
- data['pk'] = id
+ data['pk'] = pk
serializer_obj = AdminAppReleaseSerializer(app_obj, data=data, partial=True)
if serializer_obj.is_valid():
serializer_obj.save()
res.data = serializer_obj.data
- del_cache_response_by_short(app_obj.app_id)
+ del_cache_response_by_short(app_obj.app_id.app_id)
return Response(res.dict)
res.code = 1004
res.msg = "数据校验失败"
diff --git a/fir_ser/admin/views/user.py b/fir_ser/admin/views/user.py
index 42dcdcc..0d53a51 100644
--- a/fir_ser/admin/views/user.py
+++ b/fir_ser/admin/views/user.py
@@ -5,7 +5,7 @@
# date: 2021/4/11
from django.contrib import auth
-from api.models import Token, UserInfo
+from api.models import Token, UserInfo, UserCertificationInfo
from rest_framework.response import Response
from api.utils.auth import AdminTokenAuthentication
from api.utils.serializer import AdminUserInfoSerializer
@@ -37,7 +37,7 @@ class UserInfoView(APIView):
def get(self, request):
res = BaseResponse()
filter_data = {}
- filter_fileds = ["id", "mobile", "username", "email", "first_name", "certification", ]
+ filter_fileds = ["id", "mobile", "username", "email", "first_name"]
for filed in filter_fileds:
f_value = request.query_params.get(filed, None)
if f_value:
@@ -72,6 +72,9 @@ class UserInfoView(APIView):
users_serializer = AdminUserInfoSerializer(user_obj, data=data, partial=True)
if users_serializer.is_valid():
users_serializer.save()
+ certification = data.get("certification", None)
+ if certification and certification != -1:
+ UserCertificationInfo.objects.filter(user_id=user_obj).update(status=data["certification"])
res.data = users_serializer.data
return Response(res.dict)
res.code = 1004
diff --git a/fir_ser/api/models.py b/fir_ser/api/models.py
index 8ce3f54..8d53fa1 100644
--- a/fir_ser/api/models.py
+++ b/fir_ser/api/models.py
@@ -405,7 +405,7 @@ class UserCertificationInfo(models.Model):
card = models.CharField(max_length=128, null=False, verbose_name="身份证号码")
addr = models.CharField(max_length=128, null=False, verbose_name="居住地")
mobile = models.BigIntegerField(verbose_name="手机号码", unique=True, null=False)
- status_choices = ((0, '审核中'), (1, '审核成功'), (2, '审核失败'))
+ status_choices = ((-1, '待认证'),(0, '认证中'), (1, '认证成功'), (2, '认证失败'))
status = models.SmallIntegerField(choices=status_choices, default=0, verbose_name="审核状态")
msg = models.CharField(max_length=512, null=True, blank=True, verbose_name="备注")
created_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
diff --git a/fir_ser/api/utils/serializer.py b/fir_ser/api/utils/serializer.py
index e70334f..5ceb38e 100644
--- a/fir_ser/api/utils/serializer.py
+++ b/fir_ser/api/utils/serializer.py
@@ -20,7 +20,12 @@ def get_download_url_from_context(self, obj, key, url, force_new=False):
if self.context.get("storage", None) and self.context.get("storage") != "undefined":
storage = self.context.get("storage", None)
else:
- storage = Storage(obj.user_id)
+ if isinstance(obj, models.Apps):
+ storage = Storage(obj.user_id)
+ elif isinstance(obj, models.AppReleaseInfo):
+ storage = Storage(obj.app_id.user_id)
+ else:
+ storage = None
if storage:
icon_url = storage.get_download_url(os.path.basename(url), 600, key, force_new)
return icon_url
@@ -75,7 +80,7 @@ class AdminUserInfoSerializer(UserInfoSerializer):
class Meta:
model = models.UserInfo
exclude = ["password", "api_token"]
- read_only_fields = ["id", "head_img", "free_download_times", "certification", "last_login",
+ read_only_fields = ["id", "head_img", "free_download_times", "last_login",
"is_superuser", "last_name", "is_staff", "uid", "storage_active", "supersign_active",
"date_joined", "download_times", "all_download_times", "storage", "groups",
"user_permissions"]
@@ -95,6 +100,11 @@ class AdminUserInfoSerializer(UserInfoSerializer):
def get_storage_choices(self, obj):
return get_choices_dict(models.AppStorage.storage_choices[1:])
+ certification_status_choices = serializers.SerializerMethodField()
+
+ def get_certification_status_choices(self, obj):
+ return get_choices_dict(models.UserCertificationInfo.status_choices)
+
def update(self, instance, validated_data):
return super(AdminUserInfoSerializer, self).update(instance, validated_data)
@@ -171,7 +181,7 @@ class AdminAppsSerializer(AppsSerializer):
class Meta:
model = models.Apps
fields = "__all__"
- read_only_fields = ["id", "app_id", "user_id", "bundle_id", "count_hits","updated_time","created_time"]
+ read_only_fields = ["id", "app_id", "user_id", "bundle_id", "count_hits", "updated_time", "created_time"]
status_choices = serializers.SerializerMethodField()
@@ -188,10 +198,15 @@ class AdminAppsSerializer(AppsSerializer):
def get_supersign_type_choices(self, obj):
return get_choices_dict(obj.supersign_type_choices)
+ release_count = serializers.SerializerMethodField()
+
+ def get_release_count(self, obj):
+ return models.AppReleaseInfo.objects.filter(app_id=obj).count()
+
def update(self, instance, validated_data):
- print(validated_data)
return super(AdminAppsSerializer, self).update(instance, validated_data)
+
class AppsShortSerializer(serializers.ModelSerializer):
class Meta:
model = models.Apps
@@ -224,7 +239,8 @@ class AppsShortSerializer(serializers.ModelSerializer):
master_release_obj = get_app_master_obj_from_context(self, obj)
if master_release_obj:
key = ''
- icon_url = get_download_url_from_context(self, obj, key, os.path.basename(master_release_obj.icon_url), True)
+ icon_url = get_download_url_from_context(self, obj, key, os.path.basename(master_release_obj.icon_url),
+ True)
datainfo = {
"app_version": master_release_obj.app_version,
"icon_url": icon_url,
@@ -296,9 +312,9 @@ class AppReleaseSerializer(serializers.ModelSerializer):
class AdminAppReleaseSerializer(AppReleaseSerializer):
class Meta:
- model = models.Apps
+ model = models.AppReleaseInfo
fields = "__all__"
- read_only_fields = ["id", "app_id", "release_id", "is_master"]
+ read_only_fields = ["id", "app_id", "release_id", "binary_size"]
release_choices = serializers.SerializerMethodField()
@@ -306,8 +322,15 @@ class AdminAppReleaseSerializer(AppReleaseSerializer):
return get_choices_dict(obj.release_choices)
def update(self, instance, validated_data):
+ print(validated_data)
+ if validated_data.get("is_master", False):
+ models.AppReleaseInfo.objects.filter(app_id=instance.app_id).update(**{"is_master": False})
+ else:
+ if "is_master" in validated_data and validated_data.get("is_master") != True:
+ del validated_data["is_master"]
return super(AdminAppReleaseSerializer, self).update(instance, validated_data)
+
class StorageSerializer(serializers.ModelSerializer):
class Meta:
model = models.AppStorage