Commit 40914323 by 李金轩

框架更改

1 parent 0223808e
Showing 91 changed files with 3582 additions and 705 deletions
log
.DS_Store .DS_Store
node_modules/ node_modules
/dist /dist
*.zip dist.zip
label-cloud.zip
# local env files # local env files
.env.local .env.local
......
# label-cloud
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
This diff could not be displayed because it is too large.
{
"name": "label-cloud",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"dev": "vue-cli-service serve"
},
"dependencies": {
"ant-design-vue": "^2.2.0-beta.5",
"axios": "^0.21.1",
"core-js": "^3.6.5",
"element-plus": "^1.0.2-beta.28",
"jquery": "^3.6.0",
"js-cookie": "^2.2.1",
"less": "^4.1.1",
"less-loader": "^7.3.0",
"lodash": "^4.17.21",
"moment": "^2.29.1",
"vue": "^3.2.22",
"vue-router": "^4.0.8",
"vuex": "^4.0.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-plugin-vuex": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"@vue/compiler-sfc": "^3.0.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^7.0.0-0",
"sass": "^1.26.5",
"sass-loader": "^8.0.2",
"vue-cli-plugin-element-plus": "~0.0.13"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/vue3-essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
// window._serverHost = '36.112.68.214:12101'
window._serverHost = '101.201.36.180:12100' // 正式
// window._serverHost = '101.201.36.180:12200' // 测试
window._baseUrl = `http://${window._serverHost}`
window._serverHost2 = '101.201.36.180:12111'
// window._serverHost2 ='192.168.1.195:12101'
window._baseUrl2 = `http://${window._serverHost2}`
const log = console.log.bind(console)
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>logo.png">
<title>数据标注平台</title>
<script src="<%= BASE_URL %>config.js"></script>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
git status
git add *
git commit -m %1%
git pull
git push
git status
\ No newline at end of file \ No newline at end of file
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<style lang="less">
html, body, #app, .el-container {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
::-webkit-scrollbar {
width: 9px;
}
::-webkit-scrollbar-thumb {
background-color: #dddddd;
background-clip: padding-box;
border-radius: 2em;
-webkit-border-radius: 2em;
-moz-border-radius: 2em;
}
::-webkit-scrollbar-thumb:hover {
background-color: #bbb;
}
.flex-vertical-center {
display: flex;
align-items: center;
}
.flex-horizontal-center {
display: flex;
justify-content: center;
}
</style>
import _ from 'lodash'
export const isEmptyValue = function(o) {
return [undefined, null].includes(o)
}
export const isNotEmptyValue = function(o) {
return !isEmptyValue(o)
}
export const isArray = function(o) {
return Array.isArray(o)
}
export const isNotArray = function(o) {
return !isArray(o)
}
export const isEmptyArray = function(o) {
return isArray(o) && o.length === 0
}
export const isNotEmptyArray = function(o) {
return !isEmptyArray(o)
}
export const isObject = function(o) {
return Object.prototype.toString.call(o) === '[object Object]'
}
export const isNotObject = function(o) {
return !isObject(o)
}
export const isEmptyObject = function(o) {
return isObject(o) && Object.keys(o).length === 0
}
export const isNotEmptyObject = function(o) {
return !isEmptyObject(o)
}
export const isDate = function(o) {
return Object.prototype.toString.call(o) === '[object Date]'
}
export const isNotDate = function(o) {
return !isDate(o)
}
export const isEqual = (value, other) => {
return _.isEqual(value, other)
}
export const isNotEqual = (value, other) => {
return !isEqual(value, other)
}
export const isOneOfTheseValues = function(value, expectedValueList) {
for (let expectedValue of expectedValueList)
{
if (isEqual(value, expectedValue))
{
return true
}
}
return false
}
export const isNoneOfTheseValues = function(value, unexpectedValueList) {
for (let unexpectedValue of unexpectedValueList)
{
if (isEqual(value, unexpectedValue))
{
return false
}
}
return true
}
import {isDate, isEmptyValue, isNoneOfTheseValues, isObject, isOneOfTheseValues} from "@/PublicUtil/Judgment"
import moment from "moment"
import _ from "lodash"
import Cookies from 'js-cookie'
export const getFolderColor = function(status) {
switch (status)
{
case 1:
{
return '#44D7B6'
}
case 2:
{
return '#F7B500'
}
case 3:
{
return '#6DD400'
}
case -1:
{
return '#6495ED'
}
case 4:
{
return '#FF69B4'
}
case 7:
{
return '#8B4513'
}
default:
{
return ''
}
}
}
export const getFolderTitle = function(status) {
switch (status)
{
case 1:
{
return '待标注'
}
case 2:
{
return '标注中'
}
case 3:
{
return '完成标注'
}
case -1:
{
return '被标注'
}
case 4:
{
return '优质'
}
case 7:
{
return '低质'
}
default:
{
return ''
}
}
}
export const getImageUrl = function(imageId) {
return `${window._baseUrl}/pics/image/${imageId}?token=${Cookies.get('token')}`
}
export const previewImage = function(imageUrl) {
window.open(imageUrl)
}
export const goBack = function() {
window.history.back()
}
export const getFormDataByObject = function(object) {
const formData = new FormData()
for (const key in object)
{
const value = object[key]
formData.append(key, value)
}
return formData
}
export const getCountGte = function() {
if (isEmptyValue(localStorage.getItem('countGTE')))
{
return 1
}
else
{
return localStorage.getItem('countGTE')
}
}
export const getCountLte = function() {
if (isEmptyValue(localStorage.getItem('countLTE')))
{
return 100
}
else
{
return localStorage.getItem('countLTE')
}
}
export const getFolderNum = function() {
if (isEmptyValue(localStorage.getItem('folderNum')))
{
return 10
}
else
{
return localStorage.getItem('folderNum')
}
}
export const getMinuteNum = function() {
if (isEmptyValue(localStorage.getItem('minuteNum')))
{
return 60
}
else
{
return localStorage.getItem('minuteNum')
}
}
export const getPagedList = function(list, columnNum) {
const baseArray = list
const len = baseArray.length
const lineNum = len % columnNum === 0 ? len / columnNum : Math.floor((len / columnNum) + 1)
let result = []
for (let i = 0; i < lineNum; i++)
{
// slice() 方法返回一个从开始到结束(不包括结束)选择的数组的一部分浅拷贝到一个新数组对象。且原始数组不会被修改。
const temp = baseArray.slice(i * columnNum, i * columnNum + columnNum)
result.push(temp)
}
return result
}
export const getKeyByValueInObject = function(object, value) {
return Object.keys(object).find(
(key) => {
return object[key] === value
}
)
}
export const filterEmptyValueInObject = function(object) {
if (isObject(object))
{
for (let key in object)
{
let value = object[key]
if (isOneOfTheseValues(value, ['', NaN, undefined, null]))
{
delete object[key]
}
}
return object
}
}
export const getTodayDate = function() {
return moment().startOf("day").format("yyyy-MM-DD")
}
export const setAccessedMenu = function(menu) {
localStorage.setItem('accessedMenu', encryptString(JSON.stringify(menu)))
}
export const getAccessedMenu = function() {
return JSON.parse(decryptString(localStorage.getItem('accessedMenu')))
}
/**
* encrypto 加密程序
* @param {Strng} str 待加密字符串
* @param {Number} xor 异或值
* @param {Number} hex 加密后的进制数
* @return {Strng} 加密后的字符串
*/
const encryptString = function(str, xor = 123, hex = 25) {
if (typeof str !== 'string' || typeof xor !== 'number' || typeof hex !== 'number')
{
return
}
let resultList = []
hex = hex <= 25 ? hex : hex % 25
for (let i = 0; i < str.length; i++)
{
// 提取字符串每个字符的ascll码
let charCode = str.charCodeAt(i)
// 进行异或加密
charCode = (charCode * 1) ^ xor
// 异或加密后的字符转成 hex 位数的字符串
charCode = charCode.toString(hex)
resultList.push(charCode)
}
let splitStr = String.fromCharCode(hex + 97)
let resultStr = resultList.join(splitStr)
return resultStr
}
/**
* decrypto 解密程序
* @param {Strng} str 待加密字符串
* @param {Number} xor 异或值
* @param {Number} hex 加密后的进制数
* @return {Strng} 加密后的字符串
*/
const decryptString = function(str, xor = 123, hex = 25) {
if (typeof str !== 'string' || typeof xor !== 'number' || typeof hex !== 'number')
{
return
}
let strCharList = []
let resultList = []
hex = hex <= 25 ? hex : hex % 25
// 解析出分割字符
let splitStr = String.fromCharCode(hex + 97)
// 分割出加密字符串的加密后的每个字符
strCharList = str.split(splitStr)
for (let i = 0; i < strCharList.length; i++)
{
// 将加密后的每个字符转成加密后的ascll码
let charCode = parseInt(strCharList[i], hex)
// 异或解密出原字符的ascll码
charCode = (charCode * 1) ^ xor
let strChar = String.fromCharCode(charCode)
resultList.push(strChar)
}
let resultStr = resultList.join('')
return resultStr
}
export const resetForm = function(form) {
for (let key in form)
{
form[key] = ""
}
}
export const emptyList = function(list) {
list.splice(0, list.length)
}
export const getTimestampString = function() {
return new Date().getTime().toString()
}
export const emptyObject = function(object) {
for (let key in object)
{
delete object[key]
}
}
export const cloneObject = function(targetObject, sourceObject) {
emptyObject(targetObject)
for (const key in sourceObject)
{
const value = sourceObject[key]
targetObject[key] = value
}
}
export const createFormData = function(object, fileName, file) {
let formData = new FormData()
if (isObject(object))
{
for (let key in object)
{
let value = object[key]
// if (![undefined, null].includes(value))
if (isNoneOfTheseValues(value, [undefined, null]))
{
formData.append(key, value)
}
}
}
if (file !== undefined)
{
formData.append(fileName, file)
}
return formData
}
export const copyDataList = function(targetDataList, sourceDataList) {
targetDataList.value.splice(0, targetDataList.value.length)
targetDataList.value.push(...sourceDataList)
}
export const formatPaginatedTableData = function(targetData, sourceData, total) {
const list = sourceData.list
// 添加序号
if (list !== undefined)
{
let start = (sourceData.pageNum - 1) * sourceData.pageSize
let end = start + list.length
for (let i = start; i < end; i++)
{
let item = list[i - start]
item["serialNumber"] = i + 1
}
}
copyDataList(targetData, list)
total.value = sourceData.total
}
export const addSerialNumber = function(sourceData) {
if (sourceData !== undefined)
{
for (let i = 0; i < sourceData.length; i++)
{
let item = sourceData[i]
item["serialNumber"] = i + 1
}
}
}
// 把 date 对象转换为 0000-00-00 这种日期形式
export const formatDate = function(date) {
if (isDate(date))
{
return moment(date).format("YYYY-MM-DD")
}
}
import {axiosInstance} from "@/Request/PublicAxiosInstance"
import {} from "@/PublicUtil/PublicUtil"
import imagePackageApi from '@/views/DataLabel/ImagePackage/ImagePackageApi'
export const getUserNameIdMap = function(targetData) {
axiosInstance.request(
{
method: 'GET',
url: `/users`,
}
).then(
(r) => {
const list = r.data
for (const item of list)
{
targetData[item.name] = item.id
}
}
)
}
export const getCompanyMap = function(targetData) {
axiosInstance.request(
{
method: 'GET',
url: `/accounts`,
}
).then(
(r) => {
const list = r.data
for (const item of list)
{
targetData[item.id] = item.name
}
}
)
}
export const getImagePackageMap = function(targetData) {
imagePackageApi.getImagePackageList().then(
(r) => {
const list = r.data
for (const item of list)
{
targetData[item.name] = item.id
}
}
)
}
export const getCanCreateUsernameIdMap = function() {
const currentUserType = localStorage.getItem('currentUserType')
switch (currentUserType)
{
case '0': // 超级管理员
{
return {
"超级管理员": 0,
"项目经理": 1,
"内部质检员": 2,
"外部管理员": 3,
"外部质检员": 4,
"外部标注员": 5,
"兼职标注员": 6,
"数据清洗员": 7,
}
}
case '1': // 项目经理
{
return {
"内部质检员": 2,
"外部管理员": 3,
"外部质检员": 4,
"外部标注员": 5,
"兼职标注员": 6,
}
}
case '3': // 外部管理员
{
return {
"外部质检员": 4,
"外部标注员": 5,
"兼职标注员": 6,
}
}
default:
{
return {}
}
}
}
import axios from 'axios'
import router from '@/router/index'
import Cookies from "js-cookie"
import {getTimestampString} from "@/PublicUtil/PublicUtil"
// 创建 axios 的一个实例
const axiosInstance = axios.create(
{
baseURL: window._baseUrl
}
)
const axiosInstance2 = axios.create(
{
baseURL: window._baseUrl2,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
)
// 请求拦截器
axiosInstance.interceptors.request.use(
config => {
config.headers.token = Cookies.get('token')
return config
}
)
// 响应拦截器
axiosInstance.interceptors.response.use(
(r) => {
const responseData = r.data
const message = responseData.msg
if (message === '当前会话未登录')
{
router.push(
'/'
)
}
else
{
return responseData
}
},
(e) => {
const responseData = e.response
return responseData
}
)
axiosInstance2.interceptors.response.use(
(r) => {
const responseData = r.data
return responseData
},
(e) => {
const responseData = e.response
return responseData
}
)
export {axiosInstance, axiosInstance2}
import {createApp} from 'vue'
import App from './App.vue'
import Antd from 'ant-design-vue'
import 'ant-design-vue/dist/antd.css'
import router from './router'
import store from './store'
import installElementPlus from './plugins/element'
const app = createApp(App)
installElementPlus(app)
app.use(store)
app.use(router)
app.use(Antd)
app.mount('#app')
import ElementPlus from 'element-plus'
import 'element-plus/lib/theme-chalk/index.css'
import locale from 'element-plus/lib/locale/lang/zh-cn'
export default (app) => {
app.use(ElementPlus, {locale})
}
import {createRouter, createWebHashHistory} from 'vue-router'
const menuRoute = [
{
path: '/DataLabel',
component: () => import("@/views/Main/Main.vue"),
children: [
{
path: 'ImagePackage',
component: () => import("@/views/DataLabel/ImagePackage/ImagePackage.vue"),
},
{
path: 'PeopleLabel',
component: () => import("@/views/DataLabel/PeopleLabel/PeopleLabel.vue"),
},
{
path: 'Labeling',
component: () => import("@/views/DataLabel/Labeling/Labeling.vue"),
},
{
path: 'SubmitQualityInspect',
component: () => import("@/views/DataLabel/SubmitQualityInspect/SubmitQualityInspect.vue"),
},
{
path: 'LabelWorkbook',
component: () => import("@/views/DataLabel/LabelWorkbook/LabelWorkbook.vue"),
},
]
},
{
path: '/QualityInspect',
component: () => import("@/views/Main/Main.vue"),
children: [
{
path: 'QualityInspectExamine',
component: () => import("@/views/QualityInspect/QualityInspectExamine/QualityInspectExamine.vue"),
},
]
},
{
path: '/Project',
component: () => import("@/views/Main/Main.vue"),
children: [
{
path: 'ProjectManagement',
component: () => import("@/views/Project/ProjectManagement/ProjectManagement.vue"),
},
]
},
{
path: '/BackgroundManagement',
component: () => import("@/views/Main/Main.vue"),
children: [
{
path: 'OutsourceCompany',
component: () => import("@/views/BackgroundManagement/OutsourceCompany/OutsourceCompany.vue"),
},
{
path: 'UserManagement',
component: () => import("@/views/BackgroundManagement/UserManagement/UserManagement.vue"),
},
]
},
{
path: '/DataClean',
component: () => import("@/views/Main/Main.vue"),
children: [
{
path: 'DataClean',
component: () => import("@/views/DataClean/DataClean/DataClean.vue"),
},
{
path: 'CleanManagement',
component: () => import("@/views/DataClean/CleanManagement/CleanManagement.vue"),
},
]
},
]
const route = [
{
path: '/',
redirect: '/Login',
},
{
path: '/Test',
component: () => import("@/views/Test/Test.vue"),
},
{
path: '/Login',
component: () => import("@/views/Login/Login.vue"),
},
{
path: '/ClassAmongClean',
component: () => import("@/views/Main/Main.vue"),
children: [
{
path: '',
component: () => import("@/views/ClassAmongClean/ClassAmongClean.vue"),
},
]
},
{
path: '/ClassInsideClean',
component: () => import("@/views/Main/Main.vue"),
children: [
{
path: '',
component: () => import("@/views/ClassInsideClean/ClassInsideClean.vue"),
},
]
},
{
path: '/JudgePeople',
component: () => import("@/views/Main/Main.vue"),
children: [
{
path: '',
component: () => import("@/views/JudgePeople/JudgePeople.vue"),
},
]
},
{
path: '/ClassInsideJudgePerson',
component: () => import("@/views/Main/Main.vue"),
children: [
{
path: '',
component: () => import("@/views/ClassInsideJudgePerson/ClassInsideJudgePerson.vue"),
},
]
},
...menuRoute
]
export const getUrlByTitle = function(title) {
const map = {
"标注": '/DataLabel/ImagePackage',
"提交质检": '/DataLabel/SubmitQualityInspect',
"标注工作薄": '/DataLabel/LabelWorkbook',
"质检审核": '/QualityInspect/QualityInspectExamine',
"项目管理": '/Project/ProjectManagement',
"外包公司": '/BackgroundManagement/OutsourceCompany',
"用户管理": '/BackgroundManagement/UserManagement',
"数据清洗": '/DataClean/DataClean',
"清洗管理": '/DataClean/CleanManagement',
}
return map[title]
}
const router = createRouter(
{
history: createWebHashHistory(),
routes: route
}
)
export default router
import {createStore} from 'vuex'
export default createStore(
{
state: {
accessedRouteList: [],
},
mutations: {
setAccessedRouteList(state, accessedRouteList) {
state.accessedRouteList = accessedRouteList
},
},
}
)
<template>
<a-layout>
<a-layout-sider v-model:collapsed="collapsed" :trigger="null" collapsible>
<div class="logo"/>
<a-menu theme="dark" mode="inline" v-model:selectedKeys="selectedKeys">
<a-menu-item key="1">
<user-outlined/>
<span>nav 1</span>
</a-menu-item>
<a-menu-item key="2">
<video-camera-outlined/>
<span>nav 2</span>
</a-menu-item>
<a-menu-item key="3">
<upload-outlined/>
<span>nav 3</span>
</a-menu-item>
</a-menu>
</a-layout-sider>
<a-layout>
<a-layout-header style="background: #fff; padding: 0">
<menu-unfold-outlined
v-if="collapsed"
class="trigger"
@click="() => (collapsed = !collapsed)"
/>
<menu-fold-outlined v-else class="trigger" @click="() => (collapsed = !collapsed)"/>
</a-layout-header>
<a-layout-content
:style="{ margin: '24px 16px', padding: '24px', background: '#fff', minHeight: '280px' }"
>
Content
</a-layout-content>
</a-layout>
</a-layout>
</template>
<script>
import {
UserOutlined,
VideoCameraOutlined,
UploadOutlined,
MenuUnfoldOutlined,
MenuFoldOutlined,
} from '@ant-design/icons-vue'
import {defineComponent, ref} from 'vue'
export default defineComponent({
components: {
UserOutlined,
VideoCameraOutlined,
UploadOutlined,
MenuUnfoldOutlined,
MenuFoldOutlined,
},
setup() {
return {
selectedKeys: ref(['1']),
collapsed: ref(false),
}
},
})
</script>
<style>
</style>
import {axiosInstance} from '@/Request/PublicAxiosInstance'
import {filterEmptyValueInObject} from "@/PublicUtil/PublicUtil"
class OutsourceCompanyApi {
getOutsourceCompanyList() {
return axiosInstance.request(
{
method: 'GET',
url: '/accounts',
}
)
}
addOutsourceCompany(data) {
return axiosInstance.request(
{
method: 'POST',
url: '/accounts',
data: filterEmptyValueInObject(
{
name: data.name,
managerId: data.managerId,
description: data.description,
createUser: localStorage.getItem('currentUserId'),
}
)
}
)
}
editOutsourceCompany(id, data) {
return axiosInstance.request(
{
method: 'POST',
url: `/accounts/${id}`,
data: data
}
)
}
deleteOutsourceCompany(id) {
return axiosInstance.request(
{
method: 'DELETE',
url: `/accounts/${id}`,
}
)
}
prohibitOutsourceCompany(id) {
return axiosInstance.request(
{
method: 'POST',
url: `/accounts/${id}`,
data: {
status: 0
}
}
)
}
resumeOutsourceCompany(id) {
return axiosInstance.request(
{
method: 'POST',
url: `/accounts/${id}`,
data: {
status: 1
}
}
)
}
getUserList() {
return axiosInstance.request(
{
method: 'GET',
url: `/users`,
}
)
}
}
const outsourceCompanyApi = new OutsourceCompanyApi()
export default outsourceCompanyApi
import {axiosInstance} from '@/Request/PublicAxiosInstance'
import {filterEmptyValueInObject, } from "@/PublicUtil/PublicUtil"
class UserApi {
getUserList() {
return axiosInstance.request(
{
method: 'GET',
url: '/users',
}
)
}
addUser(data) {
return axiosInstance.request(
{
method: 'POST',
url: '/users',
data: filterEmptyValueInObject(
{
username: data.username,
name: data.name,
password: data.password,
accountId: data.accountId,
type: data.type,
createUser: localStorage.getItem('currentUserId'),
}
)
}
)
}
editUser(id, data) {
return axiosInstance.request(
{
method: 'POST',
url: `/users/${id}`,
data: data
}
)
}
deleteUser(id) {
return axiosInstance.request(
{
method: 'DELETE',
url: `/users/${id}`,
}
)
}
}
const userApi = new UserApi()
export default userApi
import {axiosInstance2} from '@/Request/PublicAxiosInstance'
import {filterEmptyValueInObject,} from "@/PublicUtil/PublicUtil"
class DataCleanApi {
getDataCleanList(data) {
return axiosInstance2.request(
{
method: 'GET',
url: '/clean2/list',
params: filterEmptyValueInObject(
{
packId: data.packId,
status: data.status,
pageNum: data.pageNum,
pageSize: data.pageSize,
}
)
}
)
}
getCleanAmongResult(data) {
return axiosInstance2.request(
{
method: 'GET',
url: '/clean2/getClean2',
params: filterEmptyValueInObject(
{
id: data.id,
packId: data.packId,
}
)
}
)
}
}
const dataCleanApi = new DataCleanApi()
export default dataCleanApi
import {axiosInstance2} from '@/Request/PublicAxiosInstance'
import {filterEmptyValueInObject, getFormDataByObject} from "@/PublicUtil/PublicUtil"
class ClassInsideCleanApi {
getClassInsideCleanList(data) {
return axiosInstance2.request(
{
method: 'GET',
url: '/clean1-person/list',
params: filterEmptyValueInObject(
{
packId: data.packId,
status: data.status,
pageNum: data.pageNum,
pageSize: data.pageSize,
}
)
}
)
}
getCleanInsideResult(data) {
return axiosInstance2.request(
{
method: 'GET',
url: '/clean1-person/getClean1',
params: {
personId: data.personId,
packId: data.packId,
}
}
)
}
split(data) {
return axiosInstance2.request(
{
method: 'POST',
url: '/clean1-person/split',
data: getFormDataByObject(
{
personId: data.personId,
packId: data.packId,
picIds: data.picIds,
}
)
}
)
}
}
const classInsideCleanApi = new ClassInsideCleanApi()
export default classInsideCleanApi
.Labeling {
background: white;
}
.el-main {
margin: 0;
padding: 0;
}
.el-header {
padding: 0;
}
.isSelected {
border: 2px solid #4487f7 !important;
}
.isFolderSelected {
background: aquamarine;
}
.isSelected:after {
bottom: 0px;
right: 0px;
content: "";
position: absolute;
width: 0;
height: 0;
border-bottom: 42px solid #4487f7;
border-left: 42px solid transparent;
}
.isSelected:before {
content: '';
position: absolute;
width: 14px;
height: 8px;
background: transparent;
bottom: 12px;
right: 5px;
border: 2px solid white;
border-top: none;
border-right: none;
-webkit-transform: rotate(-55deg);
-ms-transform: rotate(-55deg);
transform: rotate(-55deg);
z-index: 9;
}
.single-image-parent {
//display: inline-block;
position: relative;
border: 2px solid white;
text-align: center;
}
.single-image {
height: 300px;
width: 100%;
cursor: pointer;
}
.right-image-folder-list {
//border-radius: 10px;
margin: 10px 0;
}
.container {
margin: 0;
padding: 0;
overflow: auto;
}
.clearfix::after {
content: '';
display: block;
clear: both;
}
.empty {
float: left;
}
.single-image-parent {
position: relative;
border: 2px solid white;
text-align: center;
}
.single-image {
height: 300px;
width: 100%;
cursor: pointer;
}
.el-row {
height: 326px !important;
}
.isSelected {
border: 2px solid #4487f7 !important;
}
.isSelected:after {
bottom: 0px;
right: 0px;
content: "";
position: absolute;
width: 0;
height: 0;
border-bottom: 42px solid #4487f7;
border-left: 42px solid transparent;
}
.isSelected:before {
content: '';
position: absolute;
width: 14px;
height: 8px;
background: transparent;
bottom: 12px;
right: 5px;
border: 2px solid white;
border-top: none;
border-right: none;
-webkit-transform: rotate(-55deg);
-ms-transform: rotate(-55deg);
transform: rotate(-55deg);
z-index: 9;
}
<template>
<div class="container clearfix" ref="containerRef" style="height: 100%">
<div class="empty" :style="{ height: emptyHeight }"></div>
<div :style="{ transform: `translateY(${translateY})` }">
<el-row v-for="row in showedList">
<el-col :span="8" v-for="item in row" @click="selectImage(item.unid)">
<div v-bind:class="{ 'isSelected': item.isSelected}"
class="single-image-parent flex-vertical-center"
@contextmenu.prevent=""
@click.right="previewImage(getImageUrl(item.picId))">
<el-image :src="getImageUrl(item.picId)"
:fit="'contain'"
class="single-image">
</el-image>
</div>
<div>
{{ item.createTime }} {{ getDirectionTitle(item.direction) }}
</div>
</el-col>
</el-row>
</div>
</div>
</template>
<script>
import {computed, onMounted, ref} from 'vue'
import {getImageUrl, getPagedList, previewImage} from '@/PublicUtil/PublicUtil'
export default {
props: {
dataList: {
default: []
},
},
setup(props, {emit}) {
const dataList = props.dataList
const containerRef = ref()
const itemHeight = 326
const start = ref(0)
const translateY = ref(0)
const showedList = computed(
() => {
return dataList.slice(start.value, start.value + 3)
}
)
const emptyHeight = itemHeight * (dataList.length + 1)
const getDirectionTitle = function(v) {
switch (v)
{
case 1:
{
return '进'
}
case -1:
{
return '出'
}
default:
{
break
}
}
}
const selectImage = function(unid) {
emit('imageClick', unid)
}
onMounted(
() => {
containerRef.value.addEventListener(
'scroll',
(event) => {
const {scrollTop} = event.target
start.value = Math.floor(scrollTop / itemHeight)
translateY.value = scrollTop + 'px'
}
)
}
)
return {
containerRef,
translateY,
itemHeight: itemHeight + 'px',
emptyHeight: emptyHeight + 'px',
// sequence
showedList,
// function
selectImage,
getDirectionTitle,
getImageUrl,
previewImage,
}
}
}
</script>
<style lang="less" scoped>
@import "./VirtualList";
</style>
import {axiosInstance2} from '@/Request/PublicAxiosInstance'
import {filterEmptyValueInObject, getFormDataByObject,} from "@/PublicUtil/PublicUtil"
import {getImagePackageMap} from '@/Request/DictionaryRequest'
class DataCleanApi {
getDataCleanList(data) {
return axiosInstance2.request(
{
method: 'GET',
url: '/pack-clean/list',
params: {
pageNum: data.pageNum,
pageSize: data.pageSize,
}
}
)
}
addDataClean(data) {
return axiosInstance2.request(
{
method: 'POST',
url: '/pack-clean',
params: filterEmptyValueInObject(
{
packId: data.packId,
name: data.name,
}
)
}
)
}
cleanInsideClean(data) {
return axiosInstance2.request(
{
method: 'POST',
url: `/cleaning/clean1`,
data: getFormDataByObject(
{
taskId: data.taskId,
score: data.score,
percent: data.percent,
}
)
}
)
}
cleanAmongClean(data) {
return axiosInstance2.request(
{
method: 'POST',
url: `/cleaning/clean2`,
data: getFormDataByObject(
{
taskId: data.taskId,
score: data.score,
percent: data.percent,
maxNum: data.maxNum,
}
)
}
)
}
completeClean(taskId) {
return axiosInstance2.request(
{
method: 'POST',
url: `/cleaning/completeClean`,
data: getFormDataByObject(
{
taskId: taskId
}
)
}
)
}
getImagePackageMap() {
return axiosInstance2.request(
{
method: 'GET',
url: `/pack-clean/listPacks`,
}
)
}
}
const dataCleanApi = new DataCleanApi()
export default dataCleanApi
import {axiosInstance2} from '@/Request/PublicAxiosInstance'
import {filterEmptyValueInObject, getFormDataByObject} from "@/PublicUtil/PublicUtil"
import {getImagePackageMap} from '@/Request/DictionaryRequest'
class DataCleanApi {
getDataCleanList(data) {
return axiosInstance2.request(
{
method: 'GET',
url: '/pack-clean/list',
params: {
pageNum: data.pageNum,
pageSize: data.pageSize,
}
}
)
}
addDataClean(data) {
return axiosInstance2.request(
{
method: 'POST',
url: '/pack-clean',
params: filterEmptyValueInObject(
{
packId: data.packId,
name: data.name,
}
)
}
)
}
clean(cleanType, taskId) {
return axiosInstance2.request(
{
method: 'POST',
url: `/cleaning/clean${cleanType}`,
data: getFormDataByObject(
{
taskId: taskId
}
)
}
)
}
completeClean(taskId) {
return axiosInstance2.request(
{
method: 'POST',
url: `/cleaning/completeClean`,
data: getFormDataByObject(
{
taskId: taskId
}
)
}
)
}
getImagePackageMap() {
return axiosInstance2.request(
{
method: 'GET',
url: `/pack-clean/listPacks`,
}
)
}
}
const dataCleanApi = new DataCleanApi()
export default dataCleanApi
.ImagePackage {
background: white;
.image-package {
background: white;
}
.name {
height: 100%;
font-size: 17px;
font-weight: bold;
font-family: PingFangSC-Medium, PingFang SC;
color: rgba(0, 0, 0, 0.8);
}
}
<template>
<a-layout class="ImagePackage">
<el-form :model="queryImagePackageForm" :inline="true" size="small">
<el-form-item label="公司:">
<el-select v-model="queryImagePackageForm.companyId" @change="onSelectCompanyInQuery" style="width: 100%">
<el-option v-for="(name, value) in companyMap" :label="name" :value="value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="项目:">
<el-select v-model="queryImagePackageForm.projectId" style="width: 100%">
<el-option v-for="(value, name) in projectMapInQuery" :label="name" :value="value"></el-option>
</el-select>
</el-form-item>
<!-- <el-form-item label="图包:">-->
<!-- <el-select v-model="queryImagePackageForm.imagePackageId" style="width: 100%">-->
<!-- <el-option v-for="(value, key) in imagePackageMapInQuery" :label="value" :value="key"></el-option>-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<el-form-item>
<el-button @click="confirmQueryImagePackage" type="primary">查询</el-button>
<el-button @click="reset">重置</el-button>
</el-form-item>
</el-form>
<el-row v-for="(row, index) in pagedTableData" v-loading="isLoading">
<el-col :span="6" v-for="(item, index) in row" style="cursor: pointer;">
<div class="image-package">
<el-row @click="gotoPeopleLabel(item.id)">
<el-col :span="4">
<img :src="require('./image/imagePackage.svg')"/>
</el-col>
<el-col :span="20">
<div class="name">
<div class="flex-vertical-center flex-horizontal-center">
图包: {{ item?.name }}
</div>
<div class="flex-vertical-center flex-horizontal-center">
公司: {{ companyMap[item?.task?.accountId] }}
</div>
<div class="flex-vertical-center flex-horizontal-center">
项目: {{ item?.task?.name }}
</div>
</div>
</el-col>
</el-row>
<a-button v-if="isDownloadShowed" @click="downloadCompletedImages(item.id)" type="link">下载</a-button>
</div>
</el-col>
</el-row>
</a-layout>
</template>
<script>
import {computed, defineComponent, reactive, ref, toRaw, toRefs, watch} from 'vue'
import {useRouter} from 'vue-router'
import peopleLabelApi from '@/views/DataLabel/PeopleLabel/PeopleLabelApi'
import {cloneObject, getKeyByValueInObject} from '@/PublicUtil/PublicUtil'
import imagePackageApi from '@/views/DataLabel/ImagePackage/ImagePackageApi'
import Cookies from 'js-cookie'
import {getCompanyMap} from '@/Request/DictionaryRequest'
import projectApi from '@/views/Project/ProjectManagement/ProjectManagementApi'
export default defineComponent(
{
setup() {
const router = useRouter()
const peopleFolderList = ref([])
const imagePackageList = ref([])
const isLoading = ref(false)
const isDownloadShowed = ref(localStorage.getItem('currentUserType') === '0')
const pagedTableData = computed(
() => {
let baseArray = imagePackageList.value
let len = baseArray.length
let n = 4 //每行显示4个
let lineNum = len % n === 0 ? len / n : Math.floor((len / n) + 1)
let result = []
for (let i = 0; i < lineNum; i++)
{
// slice() 方法返回一个从开始到结束(不包括结束)选择的数组的一部分浅拷贝到一个新数组对象。且原始数组不会被修改。
let temp = baseArray.slice(i * n, i * n + n)
result.push(temp)
}
return result
}
)
// mapping
const queryImagePackageForm = reactive(
{
companyId: '',
projectId: '',
imagePackageId: '',
}
)
const companyMap = reactive({})
const projectMapInQuery = reactive({})
const imagePackageMapInQuery = reactive({})
const downloadCompletedImages = function(packId) {
window.open(
` ${window._baseUrl}/reid/downloadLabeledPicAsZip`
+
`?packId=${packId}&token=${Cookies.get('token')}`
)
}
const gotoPeopleLabel = function(packId) {
router.push(
{
path: '/DataLabel/PeopleLabel',
query: {
packId: packId,
pageNum: 1,
}
}
)
}
const reset = function() {
for (let key in queryImagePackageForm)
{
queryImagePackageForm[key] = ''
}
}
const getProjectMapByCompanyId = async function(companyId) {
const {data} = await projectApi.getProjectList(companyId)
let map = {}
for (const project of data)
{
map[project.name] = project.id
}
return map
}
//
// const getFloorMapByprojectId = function(projectId) {
// }
const onSelectCompanyInQuery = async function(companyId) {
queryImagePackageForm.projectId = ''
queryImagePackageForm.imagePackageId = ''
const map = await getProjectMapByCompanyId(parseInt(companyId))
cloneObject(projectMapInQuery, map)
}
// const onSelectProjectInQuery = function(projectId) {
// queryImagePackageForm.imagePackageId = ''
// cloneObject(imagePackageMapInQuery, getFloorMapByprojectId(parseInt(projectId)))
// }
const confirmQueryImagePackage = function() {
isLoading.value = true
const rawData = toRaw(queryImagePackageForm)
const data = {
companyId: rawData.companyId,
projectId: rawData.projectId,
}
imagePackageApi.getImagePackageList(data).then(
(r) => {
isLoading.value = false
imagePackageList.value = r.data
}
)
}
const initialize = function() {
confirmQueryImagePackage()
getCompanyMap(companyMap)
}
initialize()
return {
// scalar
isLoading,
isDownloadShowed,
// sequence
peopleFolderList,
pagedTableData,
// mapping
queryImagePackageForm,
companyMap,
projectMapInQuery,
imagePackageMapInQuery,
// function
reset,
onSelectCompanyInQuery,
// onSelectProjectInQuery,
gotoPeopleLabel,
downloadCompletedImages,
confirmQueryImagePackage,
getKeyByValueInObject,
}
},
}
)
</script>
<style lang="less" scoped>
@import "./ImagePackage.less";
</style>
import {axiosInstance} from "@/Request/PublicAxiosInstance"
import {filterEmptyValueInObject} from "@/PublicUtil/PublicUtil"
class ImagePackageApi {
getImagePackageList(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/packs`,
params: filterEmptyValueInObject(
{
accountId: data?.companyId,
taskId: data?.projectId,
type: 1,
}
)
}
)
}
}
const imagePackageApi = new ImagePackageApi()
export default imagePackageApi
<?xml version="1.0" encoding="UTF-8"?>
<svg width="60px" height="60px" viewBox="0 0 60 60" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>wenjianjia</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="1.1数据标注_人行标注" transform="translate(-336.000000, -259.000000)" fill-rule="nonzero">
<g id="文件夹1" transform="translate(312.000000, 218.000000)">
<g id="wenjianjia" transform="translate(24.000000, 41.000000)">
<path d="M0,30 C0,46.5685425 13.4314575,60 30,60 C46.5685425,60 60,46.5685425 60,30 C60,13.4314575 46.5685425,0 30,0 C13.4314575,0 0,13.4314575 0,30 Z" id="路径" fill="#6F9AFF" opacity="0.15072955"></path>
<g id="编组" transform="translate(15.000000, 18.000000)">
<path d="M27.1107989,6.385231 L12.5367594,6.385231 C11.7221508,6.38536458 10.9992431,5.86424184 10.7433631,5.09242471 L10.6299287,4.75960069 C10.2020168,3.47433429 8.99689379,2.60744721 7.63980047,2.60869565 L3.15347366,2.60869565 C1.41326149,2.60994376 0.00250167591,4.01684454 0,5.75354456 L0,20.8551524 C0.00250047866,22.591411 1.41257011,23.9981295 3.15233935,24 L27.1085303,24 C28.8482995,23.9981294 30.2583691,22.591411 30.2608696,20.8551524 L30.2608696,9.53460681 C30.2583705,7.79878957 28.8489908,6.39225327 27.1096646,6.38975926" id="路径" fill="#6F9AFF"></path>
<path d="M25.5546678,0.000567944867 L7.43673523,0.000567944867 C7.20640021,-0.00923103112 6.98925259,0.108368919 6.87117036,0.306859121 C6.75308814,0.505349323 6.75308814,0.752763455 6.87117036,0.951253656 C6.98925259,1.14974386 7.20640021,1.26734381 7.43673523,1.25754483 C9.32670802,1.25669534 11.004785,2.46932433 11.601388,4.26704849 L11.7142513,4.60646621 C11.8000054,4.86347742 12.0398243,5.03695174 12.310169,5.03752666 L26.8085782,5.03752666 C27.1795791,5.04216465 27.5483824,5.09541437 27.9056087,5.1959216 C28.0942468,5.24662743 28.2956815,5.20639846 28.4505319,5.0870938 C28.6053823,4.96778914 28.6959924,4.78301189 28.6956522,4.58723251 L28.6956522,3.15036426 C28.6937851,1.41467951 27.2906327,0.00809561432 25.5591823,0.00622491766" id="路径" fill="#4076F7"></path>
</g>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file \ No newline at end of file
<template>
<el-form :model="exportDataForm" :inline="true" size="small">
<el-form-item label="公司:">
<el-select v-model="exportDataForm.companyId" @change="onSelectCompanyInQuery">
<el-option v-for="(name, value) in companyMap" :label="name" :value="value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="项目:">
<el-select v-model="exportDataForm.projectId" @change="onSelectProjectInQuery">
<el-option v-for="(value, name) in projectMapInQuery" :label="name" :value="value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="图包:">
<el-select v-model="exportDataForm.imagePackageId">
<el-option v-for="(value, name) in imagePackageMapInQuery" :label="name" :value="value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="日期:">
<el-date-picker v-model="exportDataForm.time" type="daterange"></el-date-picker>
</el-form-item>
<el-form-item>
<el-button @click="exportData" :loading="isLoading" type="primary">导出数据</el-button>
</el-form-item>
</el-form>
</template>
<script>
import {computed, defineComponent, reactive, ref, toRaw, toRefs, watch} from 'vue'
import imagePackageApi from '@/views/DataLabel/ImagePackage/ImagePackageApi'
import {cloneObject, filterEmptyValueInObject, formatDate} from '@/PublicUtil/PublicUtil'
import Cookies from 'js-cookie'
import projectApi from '@/views/Project/ProjectManagement/ProjectManagementApi'
import {getCompanyMap} from '@/Request/DictionaryRequest'
export default defineComponent(
{
setup() {
// scalar
const isLoading = ref()
// sequence
const imagePackageList = ref([])
// mapping
const exportDataForm = reactive(
{
companyId: '',
projectId: '',
imagePackageId: '',
start: '',
end: '',
time: '',
}
)
const companyMap = reactive({})
const projectMapInQuery = reactive({})
const imagePackageMapInQuery = reactive({})
// function
const exportData = function() {
const rawData = toRaw(exportDataForm)
const data = filterEmptyValueInObject(
{
accountId: rawData.companyId,
taskId: rawData.projectId,
packId: rawData.imagePackageId,
start: formatDate(rawData.time[0]),
end: formatDate(rawData.time[1]),
}
)
let url = ''
for (const key in data)
{
const value = data[key]
const t = `${key}` + '=' + value
url += '&' + t
}
window.open(
` ${window._baseUrl}/reid/export`
+
`?token=${Cookies.get('token') + url}`
)
}
const getProjectMapByCompanyId = async function(companyId) {
const {data} = await projectApi.getProjectList(companyId)
let map = {}
for (const project of data)
{
map[project.name] = project.id
}
return map
}
const getImagePackageMapByProjectId = async function(projectId) {
const {data} = await imagePackageApi.getImagePackageList(
{
projectId: projectId
}
)
let map = {}
for (const imagePackage of data)
{
map[imagePackage.name] = imagePackage.id
}
return map
}
const onSelectCompanyInQuery = async function(companyId) {
exportDataForm.projectId = ''
exportDataForm.imagePackageId = ''
const map = await getProjectMapByCompanyId(parseInt(companyId))
cloneObject(projectMapInQuery, map)
}
const onSelectProjectInQuery = async function(projectId) {
exportDataForm.imagePackageId = ''
const map = await getImagePackageMapByProjectId(parseInt(projectId))
cloneObject(imagePackageMapInQuery, map)
}
const initialize = function() {
getCompanyMap(companyMap)
}
initialize()
return {
// scalar
isLoading,
// sequence
imagePackageList,
// mapping
exportDataForm,
companyMap,
projectMapInQuery,
imagePackageMapInQuery,
// function
onSelectCompanyInQuery,
onSelectProjectInQuery,
exportData,
}
},
}
)
</script>
<style lang="less" scoped>
@import "./LabelWorkbook.less";
</style>
.Labeling {
background: white;
}
.el-main {
margin: 0;
padding: 0;
}
.el-header {
padding: 0;
}
.isFolderSelected {
background: aquamarine;
}
.isSelected {
border: 2px solid #4487f7 !important;
}
.isSelected:after {
bottom: 0px;
right: 0px;
content: "";
position: absolute;
width: 0;
height: 0;
border-bottom: 42px solid #4487f7;
border-left: 42px solid transparent;
}
.isSelected:before {
content: '';
position: absolute;
width: 14px;
height: 8px;
background: transparent;
bottom: 12px;
right: 5px;
border: 2px solid white;
border-top: none;
border-right: none;
-webkit-transform: rotate(-55deg);
-ms-transform: rotate(-55deg);
transform: rotate(-55deg);
z-index: 9;
}
.single-image-parent {
position: relative;
border: 2px solid white;
text-align: center;
}
.single-image {
height: 300px;
width: 100%;
cursor: pointer;
}
.right-image-folder-list {
//border-radius: 10px;
margin: 10px 0;
}
import {axiosInstance} from "@/Request/PublicAxiosInstance"
import {filterEmptyValueInObject, getCountGte, getCountLte} from "@/PublicUtil/PublicUtil"
class LabelingApi {
getPeopleImageList(packId, personUnid) {
return axiosInstance.request(
{
method: 'GET',
url: `/subTasks`,
params: {
packId: packId,
personUnid: personUnid,
sortName: 'create_time'
},
}
)
}
getSimilarPeopleImageFolderList(picIdArr, folderNum, packId, minutes, currentPersonUnid) {
return axiosInstance.request(
{
method: 'GET',
url: `/reid/getSimilarPerson`,
params: {
picIdArr: picIdArr,
size: folderNum,
packId: packId,
timeInterval: minutes,
currentPerson: currentPersonUnid,
},
}
)
}
completeLabel(personUnid, packId) {
return axiosInstance.request(
{
method: 'GET',
url: `/reid/setPure`,
params: {
personUnid: personUnid,
packId: packId,
},
}
)
}
mergeImagesAsNewPerson(picIdArr, packId) {
return axiosInstance.request(
{
method: 'GET',
url: `/reid/mergeAsNewPerson`,
params: {
picIdArr: picIdArr,
packId: packId,
},
}
)
}
mergeMultiplePersonsAsNewPerson(personUnidArr, packId, currentPersonUnid) {
return axiosInstance.request(
{
method: 'GET',
url: `/reid/mergePerson`,
params: {
personUnidArr: personUnidArr,
packId: packId,
currentPerson: currentPersonUnid,
},
}
)
}
mergeMultipleImagesToOnePerson(picIdArr, personUnid, packId, currentPersonUnid) {
return axiosInstance.request(
{
method: 'GET',
url: `/reid/mergeTo`,
params: {
picIdArr: picIdArr,
personUnid: personUnid,
packId: packId,
currentPerson: currentPersonUnid,
},
}
)
}
deleteImages(picIdArr, packId) {
return axiosInstance.request(
{
method: 'DELETE',
url: `/reid/deletePic`,
params: {
picIdArr: picIdArr,
packId: packId,
},
}
)
}
recycle(personUnid, subTaskIdArr, packId) {
return axiosInstance.request(
{
method: 'GET',
url: `/reid/recovery`,
params: filterEmptyValueInObject(
{
personUnid: personUnid,
subTaskIdArr: subTaskIdArr,
packId: packId,
}
),
}
)
}
highQualityExtract(personUnid, subTaskIdArr, packId, currentPersonUnid) {
return axiosInstance.request(
{
method: 'GET',
url: `/reid/mergeAndTodo`,
params: filterEmptyValueInObject(
{
personUnidArr: personUnid,
subTaskIdArr: subTaskIdArr,
packId: packId,
currentPerson: currentPersonUnid,
}
),
}
)
}
lowQualityExtract(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/reid/mergeAndLowQuality`,
params: filterEmptyValueInObject(
{
personUnidArr: data.personUnidArr,
subTaskIdArr: data.subTaskIdArr,
packId: data.packId,
currentPerson: data.currentPerson,
}
),
}
)
}
exitLabeling(personUnid, packId) {
return axiosInstance.request(
{
method: 'GET',
url: `/reid/exitLabeling`,
params: {
personUnid: personUnid,
packId: packId,
},
}
)
}
getPreviousPerson(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/reid/getOtherPeople`,
params: filterEmptyValueInObject(
{
personUnid: data.personUnid,
packId: data.packId,
type: 1,
status: data.status,
countGTE: getCountGte(),
countLTE: getCountLte(),
}
),
}
)
}
getNextPerson(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/reid/getOtherPeople`,
params: filterEmptyValueInObject(
{
personUnid: data.personUnid,
packId: data.packId,
type: 0,
status: data.status,
countGTE: getCountGte(),
countLTE: getCountLte(),
}
),
}
)
}
}
const labelingApi = new LabelingApi()
export default labelingApi
.container {
margin: 0;
padding: 0;
overflow: auto;
}
.clearfix::after {
content: '';
display: block;
clear: both;
}
.empty {
float: left;
}
.single-image-parent {
position: relative;
border: 2px solid white;
text-align: center;
}
.single-image {
height: 300px;
width: 100%;
cursor: pointer;
}
.el-row {
height: 326px !important;
}
.isSelected {
border: 2px solid #4487f7 !important;
}
.isSelected:after {
bottom: 0px;
right: 0px;
content: "";
position: absolute;
width: 0;
height: 0;
border-bottom: 42px solid #4487f7;
border-left: 42px solid transparent;
}
.isSelected:before {
content: '';
position: absolute;
width: 14px;
height: 8px;
background: transparent;
bottom: 12px;
right: 5px;
border: 2px solid white;
border-top: none;
border-right: none;
-webkit-transform: rotate(-55deg);
-ms-transform: rotate(-55deg);
transform: rotate(-55deg);
z-index: 9;
}
<template>
<div class="container clearfix" ref="containerRef" style="height: 100%">
<div class="empty" :style="{ height: emptyHeight }"></div>
<div :style="{ transform: `translateY(${translateY})` }">
<el-row v-for="row in showedList">
<el-col :span="8" v-for="item in row" @click="selectImage(item.id)">
<div v-bind:class="{ 'isSelected': item.isSelected}"
class="single-image-parent flex-vertical-center"
@contextmenu.prevent=""
@click.right="previewImage(getImageUrl(item.picId))">
<el-image :src="getImageUrl(item.picId)"
:fit="'contain'"
class="single-image">
</el-image>
</div>
<div>
{{ item.createTime }} {{ getDirectionTitle(item.direction) }}
</div>
</el-col>
</el-row>
</div>
</div>
</template>
<script>
import {computed, onMounted, ref} from 'vue'
import {getImageUrl, getPagedList, previewImage} from '@/PublicUtil/PublicUtil'
export default {
props: {
dataList: {
default: []
},
},
setup(props, {emit}) {
const dataList = props.dataList
const containerRef = ref()
const itemHeight = 326
const start = ref(0)
const translateY = ref(0)
const showedList = computed(
() => {
return dataList.slice(start.value, start.value + 3)
}
)
const emptyHeight = itemHeight * (dataList.length + 1)
const getDirectionTitle = function(v) {
switch (v)
{
case 1:
{
return '进'
}
case -1:
{
return '出'
}
default:
{
break
}
}
}
const selectImage = function(id) {
emit('imageClick', id)
}
onMounted(
() => {
containerRef.value.addEventListener(
'scroll',
(event) => {
const {scrollTop} = event.target
start.value = Math.floor(scrollTop / itemHeight)
translateY.value = scrollTop + 'px'
}
)
}
)
return {
containerRef,
translateY,
itemHeight: itemHeight + 'px',
emptyHeight: emptyHeight + 'px',
// sequence
showedList,
// function
selectImage,
getDirectionTitle,
getImageUrl,
previewImage,
}
}
}
</script>
<style lang="less" scoped>
@import "./VirtualList";
</style>
.PeopleLabel {
background: white;
}
.folder {
width: 400px;
cursor: pointer;
}
.folder-title {
color: white;
padding: 0 0 0 20px;
}
.folder-body {
//padding: 0 0 0 20px;
margin: 0 auto;
}
.folder-cover-image {
//width: 200px;
text-align: center
//padding: 0 0 0 20px;
}
.column-title-font {
padding: 0 0 0 18px
}
import {axiosInstance} from "@/Request/PublicAxiosInstance"
import {filterEmptyValueInObject} from "@/PublicUtil/PublicUtil"
class PeopleLabelApi {
getPeopleImageFolderList(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/reid/getPeople`,
params: filterEmptyValueInObject(
{
packId: data.packId,
status: data.status,
annotatorId: data.annotatorId,
page: data.pageNum,
size: data.pageSize,
countGTE: data.countGTE,
countLTE: data.countLTE,
}
),
}
)
}
enterLabeling(personUnid, packId) {
return axiosInstance.request(
{
method: 'GET',
url: `/reid/labeling`,
params: filterEmptyValueInObject(
{
personUnid: personUnid,
packId: packId,
}
),
}
)
}
searchFolder(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/subTasks`,
params: filterEmptyValueInObject(
{
personUnid_like: '%' + data.personUnid_like + '%',
packId: data.packId,
group: 'true',
sortName: 'create_time'
}
),
}
)
}
submitReview(data) {
return axiosInstance.request(
{
method: 'POST',
url: `/reid/verify`,
data: filterEmptyValueInObject(
{
personUnidArr: data.personUnidArr,
status: data.status,
}
),
}
)
}
}
const peopleLabelApi = new PeopleLabelApi()
export default peopleLabelApi
.ProjectManagement {
.el-header {
display: flex;
margin: 0 20px;
align-items: center;
background: #FFFFFF;
}
.el-main {
margin: 20px;
padding: 20px;
background: #FFFFFF;
.project-form {
padding: 40px 40px 0 20px
}
}
}
<template>
<el-container class="QualityInspectManagement">
<el-header height="50px">
<div>
<span class="title-text">提交质检</span>
</div>
</el-header>
<el-main>
<el-menu mode="horizontal" @select="handleMenuSelect" :default-active="'1'">
<el-menu-item :index="'1'">
待标注
</el-menu-item>
<el-menu-item :index="'5'">
审核驳回
</el-menu-item>
<el-menu-item :index="'6'">
审核通过
</el-menu-item>
</el-menu>
<el-table :data="qualityInspectList" v-loading="isLoading">
<el-table-column prop="taskName" label="taskName" align="center"></el-table-column>
<el-table-column prop="packName" label="packName" align="center"></el-table-column>
<el-table-column prop="accountId" label="所属公司" align="center">
<template #default="scope">
{{ companyMap[scope.row.accountId] }}
</template>
</el-table-column>
<el-table-column prop="count" label="count" align="center"></el-table-column>
<el-table-column prop="finishCount" label="finishCount" align="center"></el-table-column>
<el-table-column prop="toBeLabeledCount" label="toBeLabeledCount" align="center"></el-table-column>
<el-table-column prop="operation" label="操作" align="center">
<template #default="scope">
<el-button @click="submitInspect(scope.row.packId)" type="text">提交审核</el-button>
<el-button @click="viewDetails(scope.row.packId)" type="text">查看详情</el-button>
</template>
</el-table-column>
</el-table>
</el-main>
</el-container>
</template>
<script>
import {reactive, ref, toRaw,} from "vue"
import {
filterEmptyValueInObject, getKeyByValueInObject,
resetForm
} from "@/PublicUtil/PublicUtil"
import qualityInspectApi from './SubmitQualityInspectApi'
import {ElMessageBox} from 'element-plus'
import {ElMessage} from 'element-plus'
import {getCompanyMap} from '@/Request/DictionaryRequest'
import {useRouter} from 'vue-router'
export default {
setup() {
// scalar
const pageNum = ref(1)
const pageSize = ref(10)
const total = ref()
const isLoading = ref(false)
const router = useRouter()
let selectedMenuIndex = '1'
const qualityInspectList = ref([])
// computed
// mapping
const companyMap = reactive({})
// function
const handlePageNumChange = function(num) {
pageNum.value = num
getQualityInspectList()
}
const handlePageSizeChange = function(size) {
pageNum.value = 1
pageSize.value = size
getQualityInspectList()
}
const handleMenuSelect = function(index) {
selectedMenuIndex = index
getQualityInspectList()
}
const viewDetails = function(packId) {
router.push(
{
path: '/DataLabel/PeopleLabel',
query: {
packId: packId,
pageNum: 1,
}
}
)
}
const submitInspect = function(id) {
qualityInspectApi.submitInspect(id).then(
(r) => {
const message = r.msg
ElMessage(
{
message: `${message}`,
}
)
}
)
}
const getQualityInspectList = function() {
isLoading.value = true
qualityInspectApi.getQualityInspectList(selectedMenuIndex).then(
({data}) => {
isLoading.value = false
qualityInspectList.value = data
// formatPaginatedTableData(
// qualityInspectList,
// data,
// total,
// )
}
)
}
const initialize = function() {
getQualityInspectList()
getCompanyMap(companyMap)
}
initialize()
return {
// scalar
pageNum,
pageSize,
total,
isLoading,
qualityInspectList,
// mapping
companyMap,
// function
handlePageNumChange,
handlePageSizeChange,
getKeyByValueInObject,
handleMenuSelect,
viewDetails,
submitInspect,
}
},
}
</script>
<style lang="less" scoped>
@import "./SubmitQualityInspect.less";
</style>
import {axiosInstance} from '@/Request/PublicAxiosInstance'
import {filterEmptyValueInObject,} from "@/PublicUtil/PublicUtil"
class QualityInspectApi {
getQualityInspectList(status) {
return axiosInstance.request(
{
method: 'GET',
url: '/packs/info',
params: filterEmptyValueInObject(
{
accountId: localStorage.getItem('currentAccountId'),
status: status,
}
)
}
)
}
submitInspect(id) {
return axiosInstance.request(
{
method: 'POST',
url: `/packs/${id}`,
data: {
status: 1
}
}
)
}
}
const qualityInspectApi = new QualityInspectApi()
export default qualityInspectApi
import {axiosInstance2} from "@/Request/PublicAxiosInstance"
import {filterEmptyValueInObject, getFormDataByObject, } from "@/PublicUtil/PublicUtil"
class JudgePeopleApi {
notSamePerson(id) {
return axiosInstance2.request(
{
method: 'POST',
url: `/clean2/${id}`,
data: getFormDataByObject(
{
same: 0
}
)
}
)
}
samePerson(id) {
return axiosInstance2.request(
{
method: 'POST',
url: `/clean2/${id}`,
data: getFormDataByObject(
{
same: 1
}
)
}
)
}
}
const judgePeopleApi = new JudgePeopleApi()
export default judgePeopleApi
.Labeling {
background: white;
}
.el-main {
margin: 0;
padding: 0;
}
.el-header {
padding: 0;
}
.isSelected {
border: 2px solid #4487f7 !important;
}
.isFolderSelected {
background: aquamarine;
}
.isSelected:after {
bottom: 0px;
right: 0px;
content: "";
position: absolute;
width: 0;
height: 0;
border-bottom: 42px solid #4487f7;
border-left: 42px solid transparent;
}
.isSelected:before {
content: '';
position: absolute;
width: 14px;
height: 8px;
background: transparent;
bottom: 12px;
right: 5px;
border: 2px solid white;
border-top: none;
border-right: none;
-webkit-transform: rotate(-55deg);
-ms-transform: rotate(-55deg);
transform: rotate(-55deg);
z-index: 9;
}
.single-image-parent {
//display: inline-block;
position: relative;
border: 2px solid white;
text-align: center;
}
.single-image {
height: 300px;
width: 100%;
}
.right-image-folder-list {
//border-radius: 10px;
margin: 10px 0;
}
<template>
<a-form :model="loginForm">
<a-form-item label="用户名">
<a-input v-model:value="loginForm.username"/>
</a-form-item>
<a-form-item label="密码">
<a-input v-model:value="loginForm.password"/>
</a-form-item>
<a-form-item>
<a-button type="primary" @click="onSubmit">登录</a-button>
</a-form-item>
</a-form>
</template>
<script>
import {defineComponent, reactive, toRaw} from 'vue'
import {getAccessedMenu, setAccessedMenu} from '@/PublicUtil/PublicUtil'
import loginApi from '@/views/Login/LoginApi'
import Cookies from "js-cookie"
import {useRouter} from 'vue-router'
import {getUrlByTitle} from '@/router'
import {ElMessage} from 'element-plus'
export default defineComponent({
setup() {
const router = useRouter()
const loginForm = reactive(
{
username: window.location.hostname === "localhost" ? 'vion' : '',
password: window.location.hostname === "localhost" ? 'VION20050620' : '',
}
)
const onSubmit = () => {
const data = {
username: loginForm.username,
password: loginForm.password
}
loginApi.login(data).then(
(r) => {
const message = r.msg
if (message === 'success')
{
const data = r.data
const token = data.tokenInfo.tokenValue
Cookies.set("token", token)
// store.commit("setAccessedRouteList", getAccessedRouteList(r.data.menu))
setAccessedMenu(data.menu)
localStorage.setItem('currentUserId', data.id)
localStorage.setItem('currentUserType', data.type)
localStorage.setItem('currentAccountId', data.accountId)
const accessedMenu = getAccessedMenu()
const firstTitle = accessedMenu[Object.keys(accessedMenu)[0]][0]
router.push(
getUrlByTitle(firstTitle)
)
}
else
{
ElMessage(
{
message: `${message}`,
type: 'error'
}
)
}
}
)
}
return {
loginForm,
onSubmit,
}
},
})
</script>
<style scoped>
</style>
import {axiosInstance} from "@/Request/PublicAxiosInstance"
import {filterEmptyValueInObject} from "@/PublicUtil/PublicUtil"
class LoginApi {
login(data) {
return axiosInstance.request(
{
method: 'POST',
url: `/users/login`,
data: data,
}
)
}
logout() {
return axiosInstance.request(
{
method: 'GET',
url: `/users/logout`,
}
)
}
}
const loginApi = new LoginApi()
export default loginApi
File mode changed
<template>
<el-container>
<el-aside width="200px">
<div class="logo"/>
<el-menu :router="true" :default-openeds="getOpeneds()">
<el-submenu v-for="(list, name ,index) in accessedMenu" :index="index" :key="index">
<template #title>
<span>{{ name }}</span>
</template>
<el-menu-item-group>
<el-menu-item v-for="(title, i) in list" :index="getUrlByTitle(title)" :key="i">
{{
title
}}
</el-menu-item>
</el-menu-item-group>
</el-submenu>
<!-- <el-submenu :index="100">-->
<!-- <template #title>-->
<!-- <span> 数据清洗 </span>-->
<!-- </template>-->
<!-- <el-menu-item-group>-->
<!-- <el-menu-item :index="'/DataClean/DataClean'">-->
<!-- 数据清洗-->
<!-- </el-menu-item>-->
<!-- </el-menu-item-group>-->
<!-- </el-submenu>-->
</el-menu>
</el-aside>
<el-container>
<el-header style="background: #fff; padding: 0;height: 35px">
<div style="display: flex; justify-content: flex-end;">
<el-button @click="logout">退出登录</el-button>
</div>
</el-header>
<el-main>
<router-view :key="$route.fullPath"></router-view>
</el-main>
</el-container>
</el-container>
</template>
<script>
import {defineComponent, ref} from 'vue'
import {useRouter} from 'vue-router'
import {getAccessedMenu,} from '@/PublicUtil/PublicUtil'
import {getUrlByTitle} from '@/router'
import loginApi from '@/views/Login/LoginApi'
export default defineComponent({
setup() {
const accessedMenu = getAccessedMenu()
const router = useRouter()
const goto = function(path) {
router.push(path)
}
const getOpeneds = function() {
let result = []
for (let i = 0; i < 1000; i++)
{
result.push(i)
}
return result
}
const logout = function() {
loginApi.logout().then(
() => {
router.push('/')
}
)
}
const initialize = function() {
// log(accessedMenu)
}
initialize()
return {
// scalar
// sequence
// mapping
accessedMenu,
// function
goto,
getUrlByTitle,
getOpeneds,
logout,
}
},
})
</script>
<style>
</style>
import {axiosInstance} from '@/Request/PublicAxiosInstance'
import {filterEmptyValueInObject, } from "@/PublicUtil/PublicUtil"
class ProjectApi {
getProjectList(id) {
return axiosInstance.request(
{
method: 'GET',
url: '/tasks',
params: filterEmptyValueInObject(
{
accountId: id
}
)
}
)
}
addProject(data) {
return axiosInstance.request(
{
method: 'POST',
url: '/tasks',
data: filterEmptyValueInObject(
{
name: data.name,
description: data.description,
type: 1,
labelType: 0,
createUser: localStorage.getItem('currentUserId'),
}
)
}
)
}
editProject(id, data) {
return axiosInstance.request(
{
method: 'POST',
url: `/tasks/${id}`,
data: data
}
)
}
finishProject(id) {
return axiosInstance.request(
{
method: 'POST',
url: `/tasks/${id}`,
data: {
status: 0
}
}
)
}
startProject(id) {
return axiosInstance.request(
{
method: 'POST',
url: `/tasks/${id}`,
data: {
status: 1
}
}
)
}
getUsedBatchList(id) {
return axiosInstance.request(
{
method: 'GET',
url: `/packs`,
params: filterEmptyValueInObject(
{
taskId: id
}
)
}
)
}
getUnusedBatchList() {
return axiosInstance.request(
{
method: 'GET',
url: `/packs`,
params: filterEmptyValueInObject(
{
taskId_null: 'true'
}
)
}
)
}
distributeBatch(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/packs/assignTo`,
params: filterEmptyValueInObject(
{
taskId: data.taskId,
packIds: data.packIds,
}
)
}
)
}
cancelDistributeBatch(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/packs/assignTo`,
params: filterEmptyValueInObject(
{
packIds: data.packIds,
}
)
}
)
}
}
const projectApi = new ProjectApi()
export default projectApi
<template>
<el-container class="QualityInspectManagement">
<el-header height="50px">
<div>
<span class="title-text">质检审核</span>
</div>
</el-header>
<el-main>
<el-menu mode="horizontal" @select="handleMenuSelect" :default-active="'1'">
<el-menu-item :index="'1'">
待标注
</el-menu-item>
</el-menu>
<el-table :data="qualityInspectList" v-loading="isLoading">
<el-table-column prop="taskName" label="taskName" align="center"></el-table-column>
<el-table-column prop="packName" label="packName" align="center"></el-table-column>
<el-table-column prop="accountId" label="所属公司" align="center">
<template #default="scope">
{{ companyMap[scope.row.accountId] }}
</template>
</el-table-column>
<el-table-column prop="count" label="count" align="center"></el-table-column>
<el-table-column prop="finishCount" label="finishCount" align="center"></el-table-column>
<el-table-column prop="toBeLabeledCount" label="toBeLabeledCount" align="center"></el-table-column>
<el-table-column prop="operation" label="操作" align="center">
<template #default="scope">
<el-button @click="viewDetails(scope.row.packId)" type="text">查看详情</el-button>
</template>
</el-table-column>
</el-table>
</el-main>
</el-container>
</template>
<script>
import {reactive, ref, toRaw,} from "vue"
import {
filterEmptyValueInObject, getKeyByValueInObject,
resetForm
} from "@/PublicUtil/PublicUtil"
import qualityInspectApi from './QualityInspectExamineApi'
import {ElMessageBox} from 'element-plus'
import {ElMessage} from 'element-plus'
import {getCompanyMap} from '@/Request/DictionaryRequest'
import {useRouter} from 'vue-router'
export default {
setup() {
// scalar
const pageNum = ref(1)
const pageSize = ref(10)
const total = ref()
const isLoading = ref(false)
const router = useRouter()
let selectedMenuIndex = '1'
const qualityInspectList = ref([])
// computed
// mapping
const companyMap = reactive({})
// function
const handlePageNumChange = function(num) {
pageNum.value = num
getQualityInspectList()
}
const handlePageSizeChange = function(size) {
pageNum.value = 1
pageSize.value = size
getQualityInspectList()
}
const handleMenuSelect = function(index) {
selectedMenuIndex = index
getQualityInspectList()
}
const viewDetails = function(packId) {
router.push(
{
path: '/DataLabel/PeopleLabel',
query: {
packId: packId,
isReviewAccessed: true,
pageNum: 1,
}
}
)
}
const submitInspect = function(id) {
qualityInspectApi.submitInspect(id).then(
(r) => {
const message = r.msg
ElMessage(
{
message: `${message}`,
}
)
}
)
}
const getQualityInspectList = function() {
isLoading.value = true
qualityInspectApi.getQualityInspectList(selectedMenuIndex).then(
({data}) => {
isLoading.value = false
qualityInspectList.value = data
// formatPaginatedTableData(
// qualityInspectList,
// data,
// total,
// )
}
)
}
const initialize = function() {
getQualityInspectList()
getCompanyMap(companyMap)
}
initialize()
return {
// scalar
pageNum,
pageSize,
total,
isLoading,
qualityInspectList,
// mapping
companyMap,
// function
handlePageNumChange,
handlePageSizeChange,
getKeyByValueInObject,
handleMenuSelect,
viewDetails,
submitInspect,
}
},
}
</script>
<style lang="less" scoped>
@import "./QualityInspectExamine.less";
</style>
import {axiosInstance} from '@/Request/PublicAxiosInstance'
import {filterEmptyValueInObject,} from "@/PublicUtil/PublicUtil"
class QualityInspectApi {
getQualityInspectList(status) {
return axiosInstance.request(
{
method: 'GET',
url: '/packs/info',
params: filterEmptyValueInObject(
{
accountId: localStorage.getItem('currentAccountId'),
status: status,
}
)
}
)
}
submitInspect(id) {
return axiosInstance.request(
{
method: 'POST',
url: `/packs/${id}`,
data: {
status: 1
}
}
)
}
}
const qualityInspectApi = new QualityInspectApi()
export default qualityInspectApi
<template>
<div class="container" ref="container" :style="{ height: containerHeight }">
<div class="empty" :style="{ height: emptyHeight }"></div>
<ul class="list" :style="{ transform: `translateY(${translateY})` }">
<li v-for="item in listData" :key="item" class="item" :style="{ height: itemHeight }">{{ item }}</li>
</ul>
</div>
</template>
<script>
import {computed, onMounted, ref} from 'vue'
export default {
setup() {
const oriData = Array.from({length: 100}, (v, k) => k)
const itemHeight = 20
const emptyHeight = itemHeight * oriData.length
const containerHeight = window.innerHeight
const itemCount = Math.ceil(containerHeight / itemHeight)
const container = ref(null)
const start = ref(0)
const translateY = ref(0)
const listData = computed(() => {
return oriData.slice(start.value, start.value + itemCount + 1)
})
onMounted(
() => {
container.value.addEventListener(
'scroll',
e => {
const {scrollTop} = e.target
start.value = Math.floor(scrollTop / itemHeight)
translateY.value = scrollTop + 'px'
}
)
}
)
return {
listData,
container,
translateY,
containerHeight: containerHeight + 'px',
itemHeight: itemHeight + 'px',
emptyHeight: emptyHeight + 'px'
}
}
}
</script>
<style lang="less" scoped>
.container {
overflow: auto;
display: flex;
}
</style>
.datelevel{
text-align: center;
padding-bottom: 10px;
}
.data-type{
width: 100%;
text-align: center;
}
.data{
width: 100%;
height: 70px;
}
.data-select{
width: 100%;
text-align: center;
margin-top: 0.5%;
}
.button-class{
}
.param{
width: 100%;
text-align: center;
overflow: hidden;
}
.el-select{
width: 310px !important;
}
.el-select__tags{
max-width: 290px !important;
}
.input-class{
width: 200px
}
.face-data{
margin-left: 60px
}
.showData{
/* border-width:5px; */
width: 50%;
height: 460px;
/* border:3px solid gray; */
box-shadow: 0 1px 4px 0 rgba(0,0,0,0.37);
border-radius: 4px;
margin: 0 auto;
position: relative;
/* left: 50%;
margin-left: -25%; */
overflow: auto;
}
.show-span{
margin-left: 10px;
}
.clear-select{
text-align: center;
padding: 10px 0 10px 0;
}
.date-time{
height: 30px;
}
/*覆盖 element css*/
.el-input__inner {
height: 30px !important;
line-height: 30px !important;
}
.el-input__icon {
line-height: 30px !important;
}
.date-time .el-input__inner {
height: 30px !important;
line-height: 30px !important;
}
.date-time .el-input__icon {
line-height: 30px !important;
}
.el-button {
padding: 6px 20px !important;
}
.input-class {
width: 200px
}
.date-select {
width: 100%;
text-align: center;
padding: 5px;
}
/* 全選 */
.mall-sel-box {
/* display: block; */
height: 22px;
font-size: 13px;
width: 150px;
height: 100%;
}
.sel-all-box {
height: 30px;
line-height: 30px;
font-size: 14px;
padding: 0 20px;
position: relative;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #606266;
box-sizing: border-box;
cursor: pointer;
}
.sel-all-box.selected {
color: #409EFF;
font-weight: 700;
background-color: #fff;
}
.sel-all-box.selected .custom-checkbox__inner {
background-color: #409eff;
border-color: #409eff;
}
.sel-all-box.selected .custom-checkbox__inner:after {
transform: rotate(45deg) scaleY(1);
}
.custom-checkbox__input {
white-space: nowrap;
cursor: pointer;
outline: none;
display: inline-block;
line-height: 1;
position: relative;
vertical-align: middle;
}
.custom-checkbox__inner {
display: inline-block;
position: relative;
border: 1px solid #dcdfe6;
border-radius: 2px;
box-sizing: border-box;
width: 14px;
height: 14px;
background-color: #fff;
z-index: 1;
transition: border-color .05s cubic-bezier(.71, -.46, .29, 1.46), background-color .05s cubic-bezier(.71, -.46, .29, 1.46);
}
.custom-checkbox__inner:after {
box-sizing: content-box;
content: "";
border: 1px solid #fff;
border-left: 0;
border-top: 0;
height: 7px;
left: 4px;
position: absolute;
top: 1px;
transform: rotate(45deg) scaleY(0);
width: 3px;
transition: transform .05s cubic-bezier(.71, -.46, .88, .6) .05s;
transform-origin: center;
}
.el-select-dropdown.is-multiple .el-select-dropdown__item.selected::after {
content: none;
}
.el-select-dropdown.is-multiple .el-select-dropdown__item.selected .custom-checkbox__inner {
background-color: #409eff;
border-color: #409eff;
}
.el-select-dropdown.is-multiple .el-select-dropdown__item.selected .custom-checkbox__inner:after {
transform: rotate(45deg) scaleY(1);
}
.center-div {
position: absolute;
left: 50%;
margin-left: -12%;
}
.center-progress {
display: inline-block;
margin-left: 38%;
}
.center-repairprogress {
display: inline-block;
}
.check-box {
}
.top-box {
}
.el-checkbox-group {
padding-top: 1px;
}
.el-checkbox:first-child {
margin-left: 55px
}
.el-checkbox+.el-checkbox {
margin-left: 70px;
}
.el-checkbox:last-child {
margin-left: 75px
}
.el-checkbox {
padding: 1px 0 1px 0;
}
.el-checkbox__inner{
width: 15px;
height: 15px;
}
.el-checkbox__label {
font-size: 16px
}
.level-div {
font-size: 18px;
padding: 0px 0px 0px 30px;
}
.level-box :first-child{
padding-top: 22px;
}
.bloc-mall-box {
text-align: center;
width: 50%;
float: left;
}
.line-progress {
display: block;
width: 405px;
background-color: #ebeef5;
height: 18px;
border-radius: 20px;
margin-left: 50px;
margin-top: -20px;
}
.websocket-line {
height: 18px;
/* border-radius: 20px; */
margin-left: 50px;
margin-top: -18px;
background-color: #409EFF;
position: relative;
z-index: 999;
}
.check-box .websocket-line:nth-of-type(1) {
border-top-left-radius: 20px;
border-bottom-left-radius: 20px;
}
.check-box .websocket-line:nth-of-type(2) {
border-top-left-radius: 20px;
border-bottom-left-radius: 20px;
}
.check-box :last-child {
border-top-right-radius: 20px;
border-bottom-right-radius: 20px;
}
.tooltip-div {
height:50px;
background-color: #fff;
position:absolute;
z-index: 9999;
text-align: center;
border:2px solid black;
border-radius: 10px;
}
No preview for this file type
This diff could not be displayed because it is too large.
[v-cloak] {
display: none;
}
html, body, #app {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
.container {
width: 100%;
height: 100%;
padding-top: 10px;
max-width: 1200px;
margin: 0 auto;
box-sizing: border-box;
}
.query-box {
width: 100%;
display: table;
}
.query-box + .query-box {
padding-top: 10px;
}
.query-item {
display: table-cell;
text-align: right;
width: 50%;
}
.query-item+.query-item {
padding-left: 20px;
text-align: left;
}
.query-select {
font-size: 13px;
}
.query-item__title {
font-size: 14px;
}
.query-button {
margin-left: 20px;
}
.showData{
width: 50%;
height: 460px;
min-width: 600px;
box-shadow: 0 1px 4px 0 rgba(0,0,0,0.37);
border-radius: 4px;
margin: 0 auto;
position: relative;
overflow: auto;
}
.result-wrapper {
/* padding: 0 20px; */
width: 50%;
min-width: 600px;
box-shadow: 0 1px 4px 0 rgba(0,0,0,0.37);
border-radius: 4px;
margin: 20px auto 0;
position: relative;
overflow: auto;
}
.result-header {
text-align: center;
font-size: 16px;
padding: 10px 0;
box-shadow: 0px 0px 3px 0 rgba(0,0,0,.2);
/* margin: 10px 0 0; */
}
.result-content {
font-size: 14px;
padding: 0 20px 20px;
}
.result-item {
padding-right: 8px;
box-sizing: border-box;
}
.result-item + .result-item {
margin-top: 10px;
}
.empty-data {
text-align: center;
padding: 10px 0;
font-size: 14px;
}
.result-page {
margin: 8px 0;
}
.result-page span + .result-page span {
padding: 0 5px;
}
/* .result-progress-wrapper {
margin: 20px 0 10px;
} */
.result-progress-wrapper::after,
.result-progress-wrapper::before {
content: '';
display: table;
}
.result-progress-wrapper::after {
clear: both;
}
.result-progress-left {
float: left;
}
.result-progress-right {
width: 100%;
padding-left: 88px;
box-sizing: border-box;
}
.result-progress {
height: 26px;
margin-bottom: 4px;
position: relative;
border-radius: 100px;
/* box-shadow: 0px 0px 2px 0 rgba(0,0,0,1); */
background-color: #ebeef5;
overflow: hidden;
}
.result-progress__inner {
width: 0;
position: absolute;
left: 0;
top: 0;
height: 100%;
color: #fff;
background: #409EFF;
/* background-image: linear-gradient(#86bef7, #409eff); */
border-radius: inherit;
text-align: right;
transition: width 0.1s linear;
}
.result-progress__text {
display: inline-block;
margin: 0 5px;
vertical-align: middle;
}
.result-progress-right span {
padding-left: 10px;
}
.pagination-page {
float: right;
padding-right: 10px;
}
.result-footer {
padding: 12px 20px;
font-size: 16px;
box-shadow: 0px 0px 3px 0 rgba(0,0,0,.2);
}
.result-footer::after,
.result-footer::before {
content: '';
display: table;
}
.result-footer::after {
clear: both;
}
.result-intro {
float: left;
}
.result-clear-btn {
float: right;
border-radius: 20px;
}
/* login */
#loginApp {
width: 100%;
height: 100%;
}
.login-container {
width: 100%;
height: 100%;
background: url(../image/login_bg.png) no-repeat;
background-size: 100% 100%;
text-align: right;
}
.login-form {
display: inline-block;
width: 20%;
padding-top: 30vh;
margin-right: 10%;
color: #fff;
box-sizing: border-box;
}
.login-title {
text-align: left;
}
input::-webkit-autofill {
background-color: transparent;
box-shadow: 0 0 0 1000px rgba(255, 255, 255, 0) inset !important;
-webkit-box-shadow: 0 0 0 1000px rgba(255, 255, 255, 0) inset !important;
-webkit-text-fill-color: #fff !important;
transition: background-clor 5000s ease-in-out 0s;
}
@keyframes move {
0% {
background-position: 0 0;
}
100% {
background-position: 30px 30px;
}
}
/* cover elementui stylesheet*/
.scrollbar-wrapper {
height: 100%;
height: 376px;
max-height: 376px;
overflow-x: hidden !important;
}
.el-scrollbar__bar.is-vertical {
right: 0px;
}
.el-scrollbar {
height: 100%;
}
const API = {
Login: '/users/login',
Accounts: '/accounts',
Malls: '/malls',
Gates: '/gates',
Devices: '/devices',
Channels: '/channels',
Mall: '/mall/',
FaceRecognitionsCount: '/faceRecognitions/count',
SimulationFaceRecognition: '/simulation/faceRecognition',
SimulationCountData: '/simulation/countData',
PreviewCountData: '/preview/countData',
mallStaffFeature: '/mall/staffFeature',
MallFeature: '/mall/feature',
MallStaffPool: '/mall/staffPool',
MallCustomPool: '/mall/customPool',
MallStaff: '/mall/staff',
MallCustom: '/mall/custom'
}
const WSAPI = {
RecalSchedule: '/recal/schedule/'
}
This diff could not be displayed because it is too large.
window._serverHost = window.location.hostname === 'localhost' ? 'store.keliuyun.com:9998' : window.location.host
window._baseUrl = `http://${window._serverHost}`
window._CONF_ = {
reportApiUrl: '',
apiUrl: window._baseUrl,
webSockUrl: ''
}
const log = console.log.bind(console)
/**
* [MDN](https://developer.mozilla.org/zh-CN/docs/Web/API/Document/cookie#Syntax)
*/
const Cookies = {
get: function (sKey) {
return decodeURIComponent(
document.cookie.replace(
new RegExp(
"(?:(?:^|.*;)\\s*" +
encodeURIComponent(sKey).replace(/[-.+*]/g, "\\$&") +
"\\s*\\=\\s*([^;]*).*$)|^.*$"
), "$1"
)
) || null
},
/**
* 写入
* @param {string} sKey necessary
* @param {string} sValue necessary
* @param {number|null|date|object|Infinity|string} vEnd optional
* @param {string|null} sPath optional
* @param {string|null} sDomain optional
* @param {boolean|null} bSecure optional
*/
set: function (sKey, sValue, vEnd, sPath, sDomain, bSecure) {
if (!sKey ||
/^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)
) {
return false
}
let sExpires = ''
if (vEnd) {
switch (vEnd.constructor) {
case Number:
sExpires = vEnd === Infinity
? '; expires=Fri, 31 Dec 9999 23:59:59 GMT'
: '; max-age=' + vEnd
break;
case String:
sExpires = '; expires=' + vEnd
break;
case Date:
sExpires = '; expires=' + vEnd.toUTCString()
break;
}
}
document.cookie = encodeURIComponent(sKey) + '=' +
encodeURIComponent(sValue) + sExpires +
(sDomain ? '; domain=' + sDomain : '') +
(sPath ? '; path=' + sPath : '') +
(bSecure ? '; secure' : '')
return true
},
remove: function (sKey, sPath, sDomain) {
if (!sKey || !this.has(sKey)) return false
document.cookie = encodeURIComponent(sKey) +
'=; expires=Thu, 01 Jan 1970 00:00:00 GMT' +
(sDomain ? '; domain=' + sDomain : '') +
(sPath ? '; path=' + sPath : '')
return true
},
has: function (sKey) {
return (
new RegExp('(?:^|;\\s*)' +
encodeURIComponent(sKey).replace(/[-.+*]/g, '\\$&') +
'\\s*\\='
)
).test(document.cookie)
},
keys: function () {
let aKeys = document.cookie.replace(
/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g,
''
).split(/\s*(?:\=[^;]*)?;\s*/)
for (let nIdx = 0;nIdx < aKeys.length;nIdx++) {
aKeys[nIdx] = decodeURIComponent(aKeys[nIdx])
}
return aKeys
}
}
This diff could not be displayed because it is too large.
(function() {
console.log('location', location, Cookies.get('atoken'))
if (!Cookies.get('atoken')) {
window.location.replace(window.location.href + 'login.html')
}
})()
\ No newline at end of file \ No newline at end of file
const Axios = axios.create({
baseURL: window._CONF_.apiUrl,
timeout: 0,
withCredentials: true,
headers: {
"Content-Type": "application/json;charset=UTF-8"
}
})
Axios.interceptors.request.use(
config => {
// const atoken = Cookies.get('atoken')
// console.log('atoken', atoken)
// atoken && (config.headers.Authorization = atoken)
return config
},
error => {
return Promise.reject(error)
}
)
Axios.interceptors.response.use(
res => {
// if (res.data.enote || res.data.code === 401) {
// ELEMENT.MessageBox.alert('授权到期, 请重新登录', '提示', {
// confirmButtonText: '确定',
// callback: action => {
// console.log('action', action)
// window.location.replace(window.location.href + 'login.html')
// }
// });
// } else {
return Promise.resolve(res.data)
// }
},
error => {
console.error(error)
return Promise.reject(error)
}
)
function get(url, params = {}, config = {}) {
params['s'] = +new Date()
return Axios.get(url, {...config, params})
}
function post(url, params, config = {}) {
return Axios.post(url, params, config)
}
function deletes(url, params, config = {}) {
return Axios.delete(url, params, config)
}
function put(url, params, config = {}) {
return Axios.put(url, params, config)
}
This diff could not be displayed because it is too large.
const path = require('path')
const webpack = require('webpack')
const resolve = dir => {
return path.join(__dirname, dir)
}
// 项目部署基础
// 默认情况下,我们假设你的应用将被部署在域的根目录下,
// 例如:https://www.my-app.com/
// 默认:'/'
// 如果您的应用程序部署在子路径中,则需要在这指定子路径
// 例如:https://www.foobar.com/my-app/
// 需要将它改为'/my-app/'
const BASE_URL = process.env.NODE_ENV === 'production'
? './'
: '/'
console.log('process.env.NODE_ENV', process.env.NODE_ENV)
module.exports = {
// Project deployment base
// By default we assume your app will be deployed at the root of a domain,
// e.g. https://www.my-app.com/
// If your app is deployed at a sub-path, you will need to specify that
// sub-path here. For example, if your app is deployed at
// https://www.foobar.com/my-app/
// then change this to '/my-app/'
publicPath: BASE_URL,
lintOnSave: false,
// tweak internal webpack configuration.
// see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md
chainWebpack: config => {
config.plugin('provide').use(webpack.ProvidePlugin, [
{
$: 'jquery',
jquery: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
}
])
// config.resolve.alias
// .set('@', resolve('src')) // key,value自行定义,比如.set('@@', resolve('src/components'))
// .set('_c', resolve('src/components'))
// .set('_conf', resolve('config'))
// config.module
// .rule('view-design')
// .test(/view-design.src.*?js$/)
// .use('babel')
// .loader('babel-loader')
// .end()
},
// configureWebpack: config => {
// config.entry.app = ["@babel/polyfill", "./src/main.js"];
// },
// 打包时不生成.map文件
productionSourceMap: false,
// 这里写你调用接口的基础路径,来解决跨域,如果设置了代理,那你本地开发环境的axios的baseUrl要写为 '' ,即空字符串
devServer: {
proxy: {
'/malls': {
target: 'https://store.keliuyun.com/report/malls',
// changeOrigin: true
}
}
}
}
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!