| | |
| | | ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem'] |
| | | ElButton: typeof import('element-plus/es')['ElButton'] |
| | | ElCard: typeof import('element-plus/es')['ElCard'] |
| | | ElCascader: typeof import('element-plus/es')['ElCascader'] |
| | | ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] |
| | | ElCol: typeof import('element-plus/es')['ElCol'] |
| | | ElCollapse: typeof import('element-plus/es')['ElCollapse'] |
| | | ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem'] |
| | | ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider'] |
| | | ElContainer: typeof import('element-plus/es')['ElContainer'] |
| | | ElDatePicker: typeof import('element-plus/es')['ElDatePicker'] |
| | | ElDescriptions: typeof import('element-plus/es')['ElDescriptions'] |
| | | ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem'] |
| | | ElDialog: typeof import('element-plus/es')['ElDialog'] |
| | |
| | | ElMenuItem: typeof import('element-plus/es')['ElMenuItem'] |
| | | ElMenuItemGroup: typeof import('element-plus/es')['ElMenuItemGroup'] |
| | | ElOption: typeof import('element-plus/es')['ElOption'] |
| | | ElPageHeader: typeof import('element-plus/es')['ElPageHeader'] |
| | | ElPagination: typeof import('element-plus/es')['ElPagination'] |
| | | ElPopover: typeof import('element-plus/es')['ElPopover'] |
| | | ElRadioButton: typeof import('element-plus/es')['ElRadioButton'] |
| | | ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] |
| | | ElRow: typeof import('element-plus/es')['ElRow'] |
| | | ElScrollbar: typeof import('element-plus/es')['ElScrollbar'] |
| | | ElSelect: typeof import('element-plus/es')['ElSelect'] |
| | |
| | | ElTabs: typeof import('element-plus/es')['ElTabs'] |
| | | ElTag: typeof import('element-plus/es')['ElTag'] |
| | | ElText: typeof import('element-plus/es')['ElText'] |
| | | ElTooltip: typeof import('element-plus/es')['ElTooltip'] |
| | | ElTree: typeof import('element-plus/es')['ElTree'] |
| | | ElUpload: typeof import('element-plus/es')['ElUpload'] |
| | | Footer: typeof import('./components/core/Footer.vue')['default'] |
| | |
| | | // name: 'æ´æ¹å®¡æ ¸', |
| | | // }, |
| | | { |
| | | path: '/fysp/sceneInfo', |
| | | icon: 'Files', |
| | | name: 'åºæ¯ä¿¡æ¯' |
| | | }, |
| | | { |
| | | icon: 'DocumentChecked', |
| | | name: 'èªå¨è¯ä¼°', |
| | | children: [ |
| | |
| | | path: '/fysp/evaluation/evalutationRecord', |
| | | icon: 'Tickets', |
| | | name: 'è¯ä¼°è®°å½', |
| | | }, |
| | | { |
| | | path: '/fysp/evaluation/evalutationRecordRank', |
| | | icon: 'Tickets', |
| | | name: 'è¯ä¼°æå', |
| | | }, |
| | | { |
| | | path: '/fysp/evaluation/evalutationRecordEdit', |
| | | icon: 'Tickets', |
| | | name: 'è¯åè°æ´', |
| | | }, |
| | | ], |
| | | }, |
| | |
| | | icon: 'Files', |
| | | name: '坹夿¯æ' |
| | | }, |
| | | |
| | | // { |
| | | // icon: 'Search', |
| | | // name: 'ä¸å¡åæ', |
| | | // children: [ |
| | | // { |
| | | // path: '/analysis/profollow', |
| | | // icon: 'Search', |
| | | // name: 'é®é¢å¨æè·è¸ª', |
| | | // }, |
| | | // { |
| | | // path: '/analysis/proanalysis', |
| | | // icon: 'Search', |
| | | // name: 'é®é¢æ´æ¹åæ', |
| | | // }, |
| | | // { |
| | | // path: '/analysis/standardjudge', |
| | | // icon: 'Search', |
| | | // name: 'è§èæ§è¯ä¼°', |
| | | // }, |
| | | // ], |
| | | // }, |
| | | // { |
| | | // path: '/dailyreport', |
| | | // icon: 'Search', |
| | |
| | | component: () => import('@/views/fysp/config/EvalutationRule.vue') |
| | | }, |
| | | { |
| | | //è¯ä¼°åè§åä¿®æ¹é¡µé¢ |
| | | name: 'fyspEvalutationEdit', |
| | | path: '/fysp/config/evalutationRule/CompEvalutionSubRuleUpd/:subRuleId', |
| | | component: () => import('@/views/fysp/config/components/evalution/CompEvalutionSubRuleUpd.vue'), |
| | | }, |
| | | { |
| | | //è¯ä¼°æ°æ®æº |
| | | name: 'fyspEvalutationTask', |
| | | path: '/fysp/evaluation/evalutationTask', |
| | | component: () => import('@/views/fysp/evaluation/EvalutationTask.vue'), |
| | | meta: { keepAlive: false } |
| | | meta: { keepAlive: true } |
| | | }, |
| | | { |
| | | //è¯ä¼°ç®¡ç |
| | |
| | | meta: { keepAlive: true } |
| | | }, |
| | | { |
| | | //è¯ä¼°æå |
| | | name: 'fyspEvalutationRecordRank', |
| | | path: '/fysp/evaluation/evalutationRecordRank', |
| | | component: () => import('@/views/fysp/evaluation/EvalutationRecordTest.vue'), |
| | | meta: { keepAlive: true, readonly: true } |
| | | }, |
| | | { |
| | | //è¯åè°æ´ |
| | | name: 'fyspEvalutationRecordEdit', |
| | | path: '/fysp/evaluation/evalutationRecordEdit', |
| | | component: () => import('@/views/fysp/evaluation/EvalutationRecordTest.vue'), |
| | | meta: { keepAlive: true, readonly: false } |
| | | }, |
| | | { |
| | | //è¯ä¼°ç»æè¯¦æ
|
| | | name: 'fyspEvalutationEdit', |
| | | path: '/fysp/evaluation/evalutationEdit/:subTaskId', |
| | |
| | | <FYPageHeader title="è¯ä¼°ç»æè¯¦æ
"></FYPageHeader> |
| | | <el-row v-for="item in evaluation" :key="item.id"> </el-row> |
| | | <div class="btns"> |
| | | <el-button type="primary" @click="submit" :disabled="!isUpdated">æäº¤</el-button> |
| | | <!-- <el-button type="primary" @click="submit" :disabled="!isUpdated">æäº¤</el-button> --> |
| | | </div> |
| | | <div class="fixed-div"> |
| | | <span>æ»åï¼ {{ score }}</span> |
| | | </div> |
| | | <el-table |
| | | class="table-style" |
| | |
| | | <el-table-column prop="two_maxScore" label="æå¤§åå¼" width="90" /> |
| | | <el-table-column v-slot="scope" prop="three_title" label="å
·ä½é®é¢"> |
| | | <el-checkbox |
| | | :disabled="disable" |
| | | v-model="scope.row.three_select" |
| | | @change="(checked) => threeSelectChange(checked, scope.row)" |
| | | >{{ scope.row.three_title }}</el-checkbox |
| | |
| | | }, |
| | | data() { |
| | | return { |
| | | disable: false, |
| | | score: '', |
| | | tableData: [], |
| | | evaluation: [], |
| | | subTaskId: '', |
| | |
| | | }, |
| | | /** æä»· */ |
| | | submit() { |
| | | this.disable = true; |
| | | evaluateApi |
| | | .updateScore({ |
| | | subTaskId: this.subTaskId, |
| | | itemList: this.checkedUpdatedList |
| | | }) |
| | | .then((res) => { |
| | | if (res.success) { |
| | | ElMessage({ |
| | | message: res.message, |
| | | type: 'success' |
| | | }); |
| | | }else { |
| | | ElMessage({ |
| | | message: res.message, |
| | | type: 'error' |
| | | }); |
| | | } |
| | | this.disable = false; |
| | | this.score = res.data.score; |
| | | // if (res.success) { |
| | | // ElMessage({ |
| | | // message: res.message, |
| | | // type: 'success' |
| | | // }); |
| | | // }else { |
| | | // ElMessage({ |
| | | // message: res.message, |
| | | // type: 'error' |
| | | // }); |
| | | // } |
| | | }) |
| | | .catch((e) => { |
| | | this.disable = false; |
| | | }); |
| | | setTimeout(() => { |
| | | this.getList(); |
| | | }, 1000); |
| | | }, 200); |
| | | }, |
| | | /** éè¿ç¬¬ä¸çº§çidè·åä¸çº§ä»¥å顶级 */ |
| | | getSuperObjByThreeId(threeId, list, path = []) { |
| | |
| | | /** é®é¢éæ©æ¡ */ |
| | | threeSelectChange(isSelect, row) { |
| | | this.isUpdated = true; |
| | | this.submit(); |
| | | }, |
| | | /** ååå¹¶ */ |
| | | objectSpanMethod({ row, column, rowIndex, columnIndex }) { |
| | |
| | | this.subTaskId = this.$route.params.subTaskId; |
| | | evaluateApi.fetchItemEvaluation(this.subTaskId).then((res) => { |
| | | this.isUpdated = false; |
| | | this.score = res.data.score; |
| | | this.tableData = this.genTableData(res.data.details); |
| | | }); |
| | | }, |
| | |
| | | .red-cell { |
| | | background-color: red; |
| | | } |
| | | /* åºå®å®ä½ç div */ |
| | | .fixed-div { |
| | | position: fixed; |
| | | top: 7%; /* è·ç¦»é¡¶é¨ 20px */ |
| | | right: 20px; /* è·ç¦»å³ä¾§ 20px */ |
| | | width: 200px; /* div ç宽度 */ |
| | | background-color: #f2f2f2; /* èæ¯é¢è² */ |
| | | padding: 20px; /* å
è¾¹è· */ |
| | | box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); /* é´å½±ææ */ |
| | | z-index: 1000; /* ç¡®ä¿ div å¨é¡µé¢å
¶ä»å
容ä¹ä¸ */ |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <ChangeableColumnTable |
| | | @search="onSearch" |
| | | :pagination="false" |
| | | :cols="cols" |
| | | ref="tableRef" |
| | | @select-updated="selectUpdated" |
| | | @select-batch-updated="selectBatchUpdated" |
| | | > |
| | | <template #options> |
| | | <!-- åºå¿ --> |
| | | <FYOptionLocation |
| | | :allOption="false" |
| | | :level="3" |
| | | :checkStrictly="false" |
| | | v-model:value="formSearch.locations" |
| | | ></FYOptionLocation> |
| | | <!-- åºæ¯ç±»å --> |
| | | <FYOptionScene |
| | | :allOption="false" |
| | | :type="2" |
| | | v-model:value="formSearch.scenetype" |
| | | ></FYOptionScene> |
| | | <!-- æ¶é´ --> |
| | | <FYOptionTime :initValue="false" type="month" v-model:value="formSearch.time"></FYOptionTime> |
| | | </template> |
| | | <template #buttons> |
| | | <!-- <el-button icon="Download" size="default" type="success" @click="download" |
| | | >è§èæ§è¯ä¼°ä¸åææ¥å</el-button |
| | | > --> |
| | | |
| | | <CompReport |
| | | :locations="formSearch.locations" |
| | | :scenetype="formSearch.scenetype" |
| | | :time="formSearch.time" |
| | | ></CompReport> |
| | | </template> |
| | | <template #options-expand> |
| | | <!-- <div class="flex-div flex-v-center"> |
| | | <el-form-item label="é¨åæ£å"> |
| | | <el-select |
| | | style="width: 310px" |
| | | collapse-tags |
| | | collapse-tags-tooltip |
| | | v-model="partScoreHeads" |
| | | multiple |
| | | placeholder="é¨åæ£å项" |
| | | clearable |
| | | filterable |
| | | @change="onSelectionChange" |
| | | > |
| | | <el-option |
| | | v-for="item in cols.filter((item) => 'children' in item)" |
| | | :key="item" |
| | | :label="item.label" |
| | | :value="item.name" |
| | | /> </el-select |
| | | ></el-form-item> |
| | | <el-tooltip placement="bottom-start" effect="light"> |
| | | <template #content> |
| | | <el-text size="b">éä¸çæ¡ç®å¯¹åºçæ£åæ»åå°ä¼æ¾ç¤ºå¨è¡¨æ ¼ä¸çé¨åæ£ååä¸</el-text><br /> |
| | | </template> |
| | | <el-icon class="m-l-8 cursor-p" :size="16" color="var(--el-color-warning)" |
| | | ><QuestionFilled |
| | | /></el-icon> |
| | | </el-tooltip> |
| | | </div>--> |
| | | |
| | | <el-form :inline="true"> |
| | | <CompQuickSet @quick-set="setOptions"></CompQuickSet> |
| | | </el-form> |
| | | </template> |
| | | </ChangeableColumnTable> |
| | | </template> |
| | | <script> |
| | | import ChangeableColumnTable from './components/ChangeableColumnTable.vue'; |
| | | import CompReport from './components/CompReport.vue'; |
| | | import evaluateApi from '@/api/fysp/evaluateApi'; |
| | | import { useCloned } from '@vueuse/core'; |
| | | import dayjs from 'dayjs'; |
| | | import { ElMessage } from 'element-plus'; |
| | | import { useMessageBox, useMessageBoxTip } from '../../../composables/messageBox'; |
| | | export default { |
| | | components: { |
| | | ChangeableColumnTable, |
| | | CompReport, |
| | | }, |
| | | data() { |
| | | return { |
| | | partScoreHeads: [], |
| | | editRecordSwitch: false, |
| | | dataReady: false, |
| | | area: {}, |
| | | formSearch: { |
| | | locations: {}, |
| | | scenetype: {}, |
| | | time: dayjs().add(-1, 'M').date(1).toDate() |
| | | }, |
| | | refreshTable: true, |
| | | cols: [], |
| | | tableData: [] |
| | | }; |
| | | }, |
| | | methods: { |
| | | onSelectionChange() { |
| | | for (const tableItem of this.tableData) { |
| | | tableItem.partSum = 0; |
| | | for (const headItem of this.partScoreHeads) { |
| | | if (headItem in tableItem) { |
| | | tableItem.partSum += tableItem[headItem]; |
| | | } else { |
| | | tableItem.partSum = ''; |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | // æå®æ·»å çè¡¨å¤´é¡ºåº |
| | | addHead(headObj, index) { |
| | | this.cols.splice(index, 0, headObj); |
| | | }, |
| | | async selectBatchUpdated(rows, name) { |
| | | var promises = []; |
| | | for (const row of rows) { |
| | | if (!row.subTaskId || row.subTaskId == null) { |
| | | for (var attr in row) { |
| | | if (attr.endsWith('ScoreSelect')) { |
| | | row[attr] = false; |
| | | } |
| | | } |
| | | continue; |
| | | } |
| | | var checkedUpdatedList = []; |
| | | for (const attr in row) { |
| | | if (attr.endsWith('ScoreSelect') && Boolean(row[attr])) { |
| | | var id = attr.split('ScoreSelect')[0]; |
| | | checkedUpdatedList.push(id); |
| | | } |
| | | } |
| | | promises.push( |
| | | evaluateApi |
| | | .updateScore({ |
| | | subTaskId: row.subTaskId, |
| | | itemList: checkedUpdatedList |
| | | }) |
| | | .then(() => { |
| | | evaluateApi.fetchItemEvaluation(row.subTaskId).then((res) => { |
| | | this.updateChangeableData(res.data.details, res.data.score, row.subTaskId); |
| | | }); |
| | | }) |
| | | ); |
| | | } |
| | | var reSend = true; |
| | | while (promises.length !== 0 && reSend) { |
| | | reSend = false; |
| | | await Promise.allSettled(promises).then((results) => { |
| | | results.forEach((result, index) => { |
| | | if (result.status === 'fulfilled') { |
| | | } else { |
| | | // æåäºå æè¿ä¸ªpromise |
| | | promises.splice(index, 1); |
| | | } |
| | | }); |
| | | }); |
| | | |
| | | ElMessage({ |
| | | message: 'å
¨é¨æå', |
| | | type: 'success', |
| | | plain: true |
| | | }); |
| | | if (promises.length == 0) { |
| | | // ElMessage({ |
| | | // message: 'å
¨é¨æå', |
| | | // type: 'success', |
| | | // plain: true |
| | | // }); |
| | | } else { |
| | | // useMessageBoxTip({ |
| | | // confirmMsg: 'æ¯å¦éè¯', |
| | | // confirmTitle: 'æ¹éæ´æ°å¤±è´¥', |
| | | // onConfirm: async () => { |
| | | // reSend = true; |
| | | // } |
| | | // }); |
| | | } |
| | | } |
| | | }, |
| | | // é䏿´æ¹çåè° |
| | | selectUpdated(row) { |
| | | if (!row.subTaskId || row.subTaskId == null) { |
| | | for (var attr in row) { |
| | | if (attr.endsWith('ScoreSelect')) { |
| | | row[attr] = false; |
| | | } |
| | | } |
| | | return; |
| | | } |
| | | var checkedUpdatedList = []; |
| | | for (const attr in row) { |
| | | if (attr.endsWith('ScoreSelect') && Boolean(row[attr])) { |
| | | var id = attr.split('ScoreSelect')[0]; |
| | | checkedUpdatedList.push(id); |
| | | } |
| | | } |
| | | evaluateApi |
| | | .updateScore({ |
| | | subTaskId: row.subTaskId, |
| | | itemList: checkedUpdatedList |
| | | }) |
| | | .then(() => { |
| | | evaluateApi.fetchItemEvaluation(row.subTaskId).then((res) => { |
| | | this.updateChangeableData(res.data.details, res.data.score, row.subTaskId); |
| | | }); |
| | | }); |
| | | }, |
| | | _getParam() { |
| | | const { locations, scenetype, time } = this.formSearch; |
| | | return { |
| | | provincecode: locations.pCode, |
| | | provincename: locations.pName, |
| | | citycode: locations.cCode, |
| | | cityname: locations.cName, |
| | | districtcode: locations.dCode, |
| | | districtname: locations.dName, |
| | | starttime: dayjs(time).format('YYYY-MM-DD HH:mm:ss'), |
| | | scensetypeid: scenetype.value |
| | | }; |
| | | }, |
| | | // æ´æ°ä¸è¡æ°æ® |
| | | updateChangeableData(data, score, subTaskId) { |
| | | for (let index = 0; index < this.tableData.length; index++) { |
| | | const element = this.tableData[index]; |
| | | if (element.subTaskId == subTaskId) { |
| | | element.resultscorebef = score; |
| | | this.genChangeableData(data, element); |
| | | // this.tableData[index] = element; |
| | | } |
| | | } |
| | | }, |
| | | // çæå¾åæ¡ç®çæ°æ® |
| | | genChangeableData(data, tableItem) { |
| | | for (let index = 0; index < data.length; index++) { |
| | | const element = data[index]; |
| | | tableItem[`${element.id}Score`] = element.score; |
| | | if (element.select) { |
| | | tableItem[`${element.id}ScoreSelect`] = element.select; |
| | | } |
| | | var twoLevel = element.subList; |
| | | |
| | | if (!twoLevel) { |
| | | continue; |
| | | } |
| | | for (let index = 0; index < twoLevel.length; index++) { |
| | | const threeElement = twoLevel[index]; |
| | | tableItem[`${threeElement.id}Score`] = threeElement.score; |
| | | if (threeElement.select) { |
| | | tableItem[`${threeElement.id}ScoreSelect`] = threeElement.select; |
| | | } |
| | | var threeLevel = threeElement.subList; |
| | | if (!threeLevel) { |
| | | continue; |
| | | } |
| | | for (let index = 0; index < threeLevel.length; index++) { |
| | | const target = threeLevel[index]; |
| | | // å±ç¤ºå½ååè§åçåå¼ |
| | | // tableItem[`${target.id}Score`] = target.maxScore; |
| | | // å±ç¤ºå½å项çå½åå¾å |
| | | tableItem[`${target.id}Score`] = target.score; |
| | | if (target.select) { |
| | | tableItem[`${target.id}ScoreSelect`] = target.select; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | // çæå¾åæ¡ç®ç表头 |
| | | genChangeableHead(data) { |
| | | // ä¸çº§è¡¨å¤´ |
| | | for (let i = 0; i < data.length; i++) { |
| | | const element = data[i]; |
| | | const col = { |
| | | fixed: false |
| | | }; |
| | | this.cols.push(col); |
| | | col.label = element.title; |
| | | col.name = `${element.id}Score`; |
| | | |
| | | for (const attr in element) { |
| | | // äºçº§è¡¨å¤´ |
| | | let children = []; |
| | | col.children = children; |
| | | if (attr === 'subList') { |
| | | for (let j = 0; j < element[attr].length; j++) { |
| | | const twoElement = element[attr][j]; |
| | | const child = { |
| | | fixed: false |
| | | }; |
| | | children.push(child); |
| | | child.label = twoElement.title; |
| | | child.name = `${twoElement.id}Score`; |
| | | |
| | | for (const attr2 in twoElement) { |
| | | // ä¸çº§ææ |
| | | let children2 = []; |
| | | child.children = children2; |
| | | if (attr2 === 'subList') { |
| | | for (let k = 0; k < twoElement[attr2].length; k++) { |
| | | const threeElement = twoElement[attr2][k]; |
| | | const child2 = { |
| | | fixed: false |
| | | }; |
| | | children2.push(child2); |
| | | child2.label = threeElement.title; |
| | | child2.name = `${threeElement.id}Score`; |
| | | if (this.editRecordSwitch) { |
| | | child2.needSelect = true; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | // æå表头 |
| | | genRankHead() { |
| | | var head = { |
| | | name: 'rank', |
| | | label: 'æ»åæå', |
| | | // fixed: 'left' |
| | | }; |
| | | this.addHead(head, 0); |
| | | }, |
| | | // ç¼å·æ¹æ³ |
| | | makeNumber(array, propName) { |
| | | if (!(array instanceof Array)) { |
| | | return; |
| | | } |
| | | // var copy = []; |
| | | // array.forEach((item) => { |
| | | // copy.push(item); |
| | | // }); |
| | | |
| | | array.sort((a, b) => b[propName] - a[propName]); |
| | | // var maxIndex = copy.length; |
| | | var minIndex = 1; |
| | | array.forEach((item) => { |
| | | item.rank = minIndex++; |
| | | }); |
| | | }, |
| | | // æåæ°æ® |
| | | genRankData() { |
| | | this.makeNumber(this.tableData, 'resultscorebef'); |
| | | }, |
| | | // åºæ¬ä¿¡æ¯è¡¨å¤´ |
| | | genTableHeadBaseInfo(data) { |
| | | var cols = [ |
| | | { |
| | | name: 'sceneIndex', |
| | | label: 'ç¼å·', |
| | | fixed: false, |
| | | noncloseable: true |
| | | }, |
| | | { |
| | | name: 'createdate', |
| | | label: 'å·¡æ¥æ¥æ', |
| | | fixed: 'left', |
| | | }, |
| | | { |
| | | name: 'scensename', |
| | | label: 'åç§°', |
| | | fixed: 'left', |
| | | }, |
| | | { |
| | | name: 'resultscorebef', |
| | | label: 'å¾å', |
| | | fixed: false |
| | | }, |
| | | { |
| | | name: 'districtname', |
| | | label: 'åºå¿', |
| | | fixed: false |
| | | }, |
| | | { |
| | | name: 'townname', |
| | | label: 'è¡é', |
| | | fixed: false |
| | | }, |
| | | { |
| | | name: 'scenseaddress', |
| | | label: 'å°å', |
| | | fixed: false |
| | | } |
| | | ]; |
| | | for (var col of cols) { |
| | | this.cols.push(col); |
| | | } |
| | | }, |
| | | // çæåºæ¬æ°æ®ä¿¡æ¯ |
| | | genTableDataBaseInfo(data, tableItem) { |
| | | try { |
| | | tableItem.sceneIndex = data.sceneIndex; |
| | | tableItem.scensename = data.sceneName; |
| | | tableItem.districtname = data.dname; |
| | | tableItem.townname = data.tname; |
| | | if (!data.evaluation) { |
| | | tableItem.createdate = ''; |
| | | tableItem.resultscorebef = ''; |
| | | tableItem.scenseaddress = ''; |
| | | return; |
| | | } |
| | | tableItem.createdate = data.evaluation.createdate |
| | | ? dayjs(data.evaluation.createdate).format('MM-DD') |
| | | : ''; |
| | | tableItem.resultscorebef = data.evaluation.resultscorebef || 0; |
| | | tableItem.scenseaddress = data.evaluation.scenseaddress || ''; |
| | | } catch (e) { |
| | | console.log(e.message, data); |
| | | } |
| | | }, |
| | | onSearch(page, func) { |
| | | this.dataReady = false; |
| | | this.tableData = []; |
| | | this.cols = []; |
| | | const area = this._getParam(); |
| | | var expandHeadOk = false; |
| | | var baseHeadOk = false; |
| | | var showExpand = true; |
| | | evaluateApi |
| | | .fetchAutoEvaluation(area) |
| | | .then((res) => { |
| | | for (const element of res.data) { |
| | | if (element.subTaskId == null) { |
| | | showExpand = false; |
| | | // continue; |
| | | // console.log('subTask为空'); |
| | | } else { |
| | | showExpand = true; |
| | | } |
| | | var tableItem = {}; |
| | | |
| | | if (!baseHeadOk) { |
| | | this.genTableHeadBaseInfo(element); |
| | | baseHeadOk = true; |
| | | } |
| | | if (showExpand) { |
| | | evaluateApi |
| | | .fetchItemEvaluation(element.subTaskId) |
| | | .then((res) => { |
| | | const data = res.data.details; |
| | | tableItem = { |
| | | subTaskId: element.subTaskId |
| | | }; |
| | | this.tableData.push(tableItem); |
| | | try { |
| | | if (!expandHeadOk) { |
| | | this.genChangeableHead(data); |
| | | expandHeadOk = true; |
| | | } |
| | | } catch (e) { |
| | | console.log('表头åå¤å¤±è´¥', e.message); |
| | | } |
| | | this.genTableDataBaseInfo(element, tableItem); |
| | | this.genChangeableData(data, tableItem); |
| | | }) |
| | | .catch((error) => { |
| | | console.error('Error fetching item evaluation:', error); |
| | | }) |
| | | .finally(() => {}); |
| | | } else { |
| | | this.genTableDataBaseInfo(element, tableItem); |
| | | this.tableData.push(tableItem); |
| | | } |
| | | } |
| | | }) |
| | | .finally(() => { |
| | | setTimeout(() => { |
| | | this.dataReady = true; |
| | | // çææå表头 |
| | | this.genRankHead(); |
| | | this.genRankData(); |
| | | func({ data: this.tableData }); |
| | | }, 1000); |
| | | }); |
| | | }, |
| | | // åå§åè°æ´ç¶æ |
| | | initEditRecord() { |
| | | if (!Boolean(this.$route.meta.readonly)) { |
| | | this.editRecordSwitch = true; |
| | | } |
| | | }, |
| | | // åå§å |
| | | init() { |
| | | this.initEditRecord(); |
| | | }, |
| | | |
| | | setOptions(param) { |
| | | this.formSearch.locations = param.locations; |
| | | this.formSearch.scenetype = param.scenetype; |
| | | this.formSearch.sourceType = param.sourceType; |
| | | this.$refs.tableRef.onSearch(); |
| | | } |
| | | }, |
| | | created() { |
| | | this.init(); |
| | | }, |
| | | mounted() { |
| | | this.$refs.tableRef.onSearch(); |
| | | } |
| | | }; |
| | | </script> |
| | | <style scoped> |
| | | .flex-div { |
| | | display: flex; |
| | | } |
| | | .flex-v-center { |
| | | align-items: center; |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <!-- <el-button type="text" @click="reShow">æµè¯éæ°å è½½å¨æè¡¨å¤´ç»ä»¶</el-button> --> |
| | | <el-row ref="searchRef"> |
| | | <FYSearchBar @search="onSearch"> |
| | | <template #options> |
| | | <slot name="options"></slot> |
| | | </template> |
| | | <template #buttons> |
| | | <slot name="buttons"></slot> |
| | | </template> |
| | | </FYSearchBar> |
| | | </el-row> |
| | | <el-row ref="expandRef" justify="space-between"> |
| | | <el-col span="22"> |
| | | <slot name="options-expand"></slot> |
| | | </el-col> |
| | | <el-col span="2"> |
| | | <el-space :wrap="false"> |
| | | <el-text size="small">åä½</el-text> |
| | | <el-radio-group v-model="fontSize" size="small"> |
| | | <el-radio-button value="small">å°</el-radio-button> |
| | | <el-radio-button value="default">ä¸</el-radio-button> |
| | | <el-radio-button value="large">大</el-radio-button> |
| | | </el-radio-group> |
| | | <el-popover placement="bottom" :width="400" trigger="click"> |
| | | <template #reference> |
| | | <el-button type="primary" @click="genHeadTreeData">表头修æ¹</el-button> |
| | | </template> |
| | | <!-- ååºè¡¨å¤´çæ ç¶ç»æ --> |
| | | <el-tree |
| | | v-if="isOk" |
| | | :props="headTreeProps" |
| | | :data="headTreeData" |
| | | node-key="label" |
| | | show-checkbox |
| | | :default-checked-keys="showHeadLabels" |
| | | @check-change="handleHeadCheckChange" |
| | | /> |
| | | <div class="tree-btus"> |
| | | <el-button size="small" type="primary" @click="deleteSecondLevelNodes" |
| | | >ç§»é¤ææäºçº§èç¹</el-button |
| | | > |
| | | <el-button size="small" type="primary" @click="deleteThirdLevelNodes" |
| | | >ç§»é¤ææä¸çº§èç¹</el-button |
| | | > |
| | | <!-- <el-button size="small" type="primary" @click="resetCols">å¤å</el-button> --> |
| | | </div> |
| | | </el-popover> |
| | | </el-space> |
| | | </el-col> |
| | | </el-row> |
| | | <div ref="expand2Ref"> |
| | | <slot name="options-expand2"></slot> |
| | | </div> |
| | | <el-table |
| | | :data="tableData" |
| | | v-loading="loading" |
| | | :row-class-name="tableRowClassName" |
| | | table-layout="auto" |
| | | :height="tableHeight" |
| | | :size="fontSize" |
| | | @header-contextmenu="headerContextmenu" |
| | | border |
| | | > |
| | | <el-table-column |
| | | v-for="(item, index) in tableCols" |
| | | :key="item.label" |
| | | :fixed="item.fixed" |
| | | :label="item.label" |
| | | :prop="item.name" |
| | | :ref="item.name" |
| | | :sortable="item.name ? true : false" |
| | | > |
| | | <template v-slot:header v-if="item.needSelect"> |
| | | <div> |
| | | {{ item.label }} |
| | | <el-button |
| | | @click="handleHeaderBacthSelectClick(item, true, $event)" |
| | | type="primary" |
| | | size="default" |
| | | circle |
| | | > |
| | | éä¸ |
| | | </el-button> |
| | | <el-button |
| | | @click="handleHeaderBacthSelectClick(item, false, $event)" |
| | | type="success" |
| | | size="default" |
| | | circle |
| | | > |
| | | å»é¤ |
| | | </el-button> |
| | | </div> |
| | | </template> |
| | | <template v-slot:default1="scope"> |
| | | <el-checkbox |
| | | v-if="item.needSelect" |
| | | v-model="scope.row[`${item.name}Select`]" |
| | | @change="(checked) => selectChange(checked, scope.row)" |
| | | >{{ scope.row[item.name] }}</el-checkbox |
| | | > |
| | | </template> |
| | | <el-table-column |
| | | v-if="item.children && item.children.length > 0" |
| | | v-for="(item2, index2) in item.children" |
| | | :label="item2.label" |
| | | :prop="item2.name" |
| | | :ref="item2.name" |
| | | :sortable="item2.name ? true : false" |
| | | > |
| | | <template v-slot:header v-if="item2.needSelect"> |
| | | <div> |
| | | {{ item2.label }} |
| | | <el-button |
| | | @click="handleHeaderBacthSelectClick(item2, true, $event)" |
| | | type="primary" |
| | | size="default" |
| | | circle |
| | | > |
| | | éä¸ |
| | | </el-button> |
| | | <el-button |
| | | @click="handleHeaderBacthSelectClick(item2, false, $event)" |
| | | type="success" |
| | | size="default" |
| | | circle |
| | | > |
| | | å»é¤ |
| | | </el-button> |
| | | </div> |
| | | </template> |
| | | |
| | | <template v-slot:default2="scope2"> |
| | | <el-checkbox |
| | | v-if="item2.needSelect" |
| | | v-model="scope2.row[`${item2.name}Select`]" |
| | | @change="(checked) => selectChange(checked, scope2.row)" |
| | | >{{ scope2.row[item2.name] }}</el-checkbox |
| | | > |
| | | </template> |
| | | <el-table-column |
| | | v-if="item2.children && item2.children.length > 0" |
| | | v-for="(item3, index3) in item2.children" |
| | | :label="item3.label" |
| | | :prop="item3.name" |
| | | :ref="item3.name" |
| | | :sortable="item3.name ? true : false" |
| | | > |
| | | <template v-slot:header v-if="item3.needSelect"> |
| | | <div> |
| | | {{ item3.label }} |
| | | <el-button |
| | | @click="handleHeaderBacthSelectClick(item3, true, $event)" |
| | | type="primary" |
| | | size="default" |
| | | circle |
| | | > |
| | | éä¸ |
| | | </el-button> |
| | | <el-button |
| | | @click="handleHeaderBacthSelectClick(item3, false, $event)" |
| | | type="success" |
| | | size="default" |
| | | circle |
| | | > |
| | | å»é¤ |
| | | </el-button> |
| | | </div> |
| | | </template> |
| | | <template v-slot="scope3"> |
| | | <div class="flex-div"> |
| | | <!-- <div v-if="scope3.row.loader" class="loader"></div> --> |
| | | <div v-if="item3.needSelect"> |
| | | <el-checkbox |
| | | v-model="scope3.row[`${item3.name}Select`]" |
| | | @change="(checked) => selectChange(checked, scope3.row)" |
| | | >{{ scope3.row[item3.name] }}</el-checkbox |
| | | > |
| | | </div> |
| | | <div v-else> |
| | | {{ scope3.row[item3.name] }} |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table-column> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <el-pagination |
| | | v-if="pagination" |
| | | ref="paginationRef" |
| | | class="el-pagination" |
| | | v-model:current-page="currentPage" |
| | | v-model:page-size="pageSize" |
| | | :page-sizes="[10, 20, 50, 100]" |
| | | :background="true" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :total="total" |
| | | /> |
| | | </template> |
| | | |
| | | <script> |
| | | import { useCloned } from '@vueuse/core'; |
| | | export default { |
| | | props: { |
| | | cols: [], |
| | | rowClassName: undefined, |
| | | pagination: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // '' | 'small' | 'default' | 'large' |
| | | size: { |
| | | type: String, |
| | | default: 'default' |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | isOk: false, |
| | | reLoad: true, |
| | | i: 0, |
| | | headTreeData: [], |
| | | headTreeProps: { |
| | | children: 'children', |
| | | label: 'label', |
| | | disabled: 'noncloseable' |
| | | }, |
| | | tableHeight: '500', |
| | | tableData: [], |
| | | total: 0, |
| | | currentPage: 1, |
| | | pageSize: 20, |
| | | loading: false, |
| | | fontSize: 'default', |
| | | tableCols: [ |
| | | { |
| | | name: '', |
| | | label: '', |
| | | needSelect: false, |
| | | children: [] |
| | | } |
| | | ] |
| | | }; |
| | | }, |
| | | emits: ['search'], |
| | | watch: { |
| | | cols: { |
| | | handler(nValue, oValue) { |
| | | this.tableCols = nValue; |
| | | }, |
| | | immediate: true |
| | | }, |
| | | currentPage(nValue, oValue) { |
| | | if (nValue != oValue) { |
| | | this.onSearch(); |
| | | } |
| | | }, |
| | | pageSize(nValue, oValue) { |
| | | if (nValue != oValue) { |
| | | this.onSearch(); |
| | | } |
| | | }, |
| | | size: { |
| | | handler(nValue, oValue) { |
| | | if (nValue != oValue) { |
| | | this.fontSize = nValue; |
| | | } |
| | | }, |
| | | immediate: true |
| | | } |
| | | }, |
| | | computed: { |
| | | showHeadLabels() { |
| | | var result = this.collectLabels(this.cols); |
| | | |
| | | return result; |
| | | }, |
| | | cTableHeight() { |
| | | if (this.$refs.searchRef) { |
| | | const h1 = this.$refs.searchRef.$el.offsetHeight; |
| | | const h2 = this.$refs.paginationRef ? this.$refs.paginationRef.$el.offsetHeight : 0; |
| | | const h3 = this.$refs.expandRef.$el.offsetHeight; |
| | | const h4 = this.$refs.expand2Ref.offsetHeight; |
| | | |
| | | const h = h1 + h2 + h3 + h4; |
| | | // return `calc(100vh - ${h1}px - ${h2}px - var(--el-main-padding) * 2 - var(--el-header-height))`; |
| | | return `calc(100vh - ${h}px - 60px - var(--el-main-padding) * 2)`; |
| | | } else { |
| | | return '500'; |
| | | } |
| | | } |
| | | }, |
| | | methods: { |
| | | deleteLevelNodes(tree, level) { |
| | | // éåæ ä¸çæ¯ä¸ªèç¹ |
| | | tree.forEach((node) => { |
| | | if (node.children && node.children.length > 0) { |
| | | // 妿å½åèç¹çåèç¹æ°ç»ä¸ä¸ºç©ºï¼éå½è°ç¨ |
| | | this.deleteLevelNodes(node.children, level - 1); |
| | | } |
| | | }); |
| | | |
| | | // 妿å½å级å«è¾¾å°æå®çº§å«ï¼æ¸
空åèç¹æ°ç» |
| | | if (level === 1) { |
| | | tree.length = 0; |
| | | } |
| | | }, |
| | | |
| | | // å 餿æäºçº§èç¹ |
| | | deleteSecondLevelNodes() { |
| | | this.loading = true; |
| | | this.deleteLevelNodes(this.tableCols, 2); |
| | | |
| | | this.loading = false; |
| | | this.genHeadTreeData(); |
| | | }, |
| | | |
| | | // å 餿æä¸çº§èç¹ |
| | | deleteThirdLevelNodes() { |
| | | this.loading = true; |
| | | this.deleteLevelNodes(this.tableCols, 3); |
| | | this.loading = false; |
| | | this.genHeadTreeData(); |
| | | }, |
| | | deepCopyCols() { |
| | | return this.deepCopy(this.cols); |
| | | }, |
| | | resetCols() { |
| | | |
| | | this.tableCols = this.deepCopyCols(); |
| | | }, |
| | | collectLabels(nodes) { |
| | | let labels = []; // ç¨äºåå¨ isShow 为 true çèç¹ç label |
| | | |
| | | function traverseNodes(nodes) { |
| | | nodes.forEach((node) => { |
| | | // 妿 isShow 为 trueï¼å° label æ·»å å°æ°ç»ä¸ |
| | | if (!(`isShow` in node) || node.isShow) { |
| | | // labels.push(node); |
| | | labels.push(node.label); |
| | | } |
| | | |
| | | // 妿å½åèç¹æåèç¹ï¼éå½è°ç¨éå彿° |
| | | if (node.children && node.children.length > 0) { |
| | | traverseNodes(node.children); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | traverseNodes(nodes); // å¼å§éå½éå |
| | | |
| | | return labels; // è¿åæ¶éå°ç labels æ°ç» |
| | | }, |
| | | // æ´æ°isShowç¶æ |
| | | updateShowTableHead(labelValue, checked) { |
| | | function traverseNodes(nodes) { |
| | | for (let index = nodes.length - 1; index >= 0; index--) { |
| | | const node = nodes[index]; |
| | | if (node.label == labelValue) { |
| | | |
| | | // node.isShow = !node.isShow; |
| | | // setTimeout(()=>{ |
| | | // nodes.splice(index, 0, node); |
| | | // }, 1000) |
| | | nodes.splice(index, 1); |
| | | } |
| | | |
| | | // 妿å½åèç¹æåèç¹ï¼éå½è°ç¨éå彿° |
| | | if (node.children && node.children.length > 0) { |
| | | traverseNodes(node.children); |
| | | } |
| | | } |
| | | } |
| | | |
| | | traverseNodes(this.tableCols); // å¼å§éå½éå |
| | | }, |
| | | // çæè¡¨å¤´æ°æ® |
| | | genHeadTreeData() { |
| | | this.headTreeData = this.tableCols; |
| | | }, |
| | | // è¡¨å¤´ç¶ææ¹å |
| | | handleHeadCheckChange(data, checked, indeterminate) { |
| | | this.updateShowTableHead(data.label, checked); |
| | | }, |
| | | // çæéä¸ç¶æå±æ§å |
| | | genSelectPropName(name) { |
| | | return `${name}Select`; |
| | | }, |
| | | // 转ä¸ç¶æè½¬å ä¼ å
¥ä¸è¡æ°æ®åéè¦è½¬æ¢éä¸ç¶æçåå |
| | | setSelectStatus(row, name, status) { |
| | | if ((!name) in row) { |
| | | return false; |
| | | } |
| | | row[this.genSelectPropName(name)] = status; |
| | | return true; |
| | | }, |
| | | reShow() { |
| | | // setTimeout(() => { |
| | | // this.isOk = true; |
| | | // console.log("æ°æ®", this.tableData); |
| | | // }, 1000); |
| | | }, |
| | | // 表头被å³é® |
| | | headerContextmenu(column, event) { |
| | | event.preventDefault(); |
| | | for (let i = 0; i < this.tableCols.length; i++) { |
| | | var item = this.tableCols[i]; |
| | | if (item.label == column.label) { |
| | | this.tableCols.splice(i, 1); |
| | | break; |
| | | } |
| | | } |
| | | }, |
| | | handleHeaderBacthSelectClick(prop, isSelect, event) { |
| | | event.stopPropagation(); |
| | | this.tableData.forEach((element) => { |
| | | this.setSelectStatus(element, prop.name, isSelect); |
| | | }); |
| | | this.selectBatchChange(isSelect, this.tableData, this.genSelectPropName(prop.name)); |
| | | }, |
| | | initSelectStatus() { |
| | | for (let index = 0; index < this.tableData.length; index++) { |
| | | const element = this.tableData[index]; |
| | | } |
| | | }, |
| | | initTableData() { |
| | | this.initSelectStatus(); |
| | | }, |
| | | deepCopy(obj, hash = new WeakMap()) { |
| | | // 妿æ¯nullï¼ç´æ¥è¿ånull |
| | | if (obj === null) return null; |
| | | // 妿æ¯åºæ¬æ°æ®ç±»åï¼ç´æ¥è¿å |
| | | if (typeof obj !== 'object') return obj; |
| | | // 妿已æ·è´è¿ï¼ç´æ¥è¿åä¹åæ·è´çç»æ |
| | | if (hash.has(obj)) return hash.get(obj); |
| | | |
| | | // å建ä¸ä¸ªæ°çå¯¹è±¡ææ°ç» |
| | | let cloneObj = Array.isArray(obj) ? [] : {}; |
| | | // ç¼åå½åå¯¹è±¡çæ·è´ |
| | | hash.set(obj, cloneObj); |
| | | |
| | | // é彿·è´å¯¹è±¡ææ°ç»çæ¯ä¸ªå±æ§ |
| | | for (let key in obj) { |
| | | // 妿屿§å¼æ¯æ°ç»æå¯¹è±¡ï¼åé彿·è´ |
| | | cloneObj[key] = this.deepCopy(obj[key], hash); |
| | | } |
| | | return cloneObj; |
| | | }, |
| | | initCols() { |
| | | this.i = 0; |
| | | this.tableCols = this.deepCopyCols(); |
| | | this.isOk = true; |
| | | for (let index = 0; index < this.tableCols.length; index++) { |
| | | const element = this.tableCols[index]; |
| | | element.isShow = true; |
| | | } |
| | | }, |
| | | // éä¸åè° |
| | | selectChange(isSelect, row) { |
| | | row.loader = true; |
| | | this.$emit('select-updated', row); |
| | | setTimeout(() => { |
| | | row.loader = false; |
| | | }, 1000); |
| | | }, |
| | | // æ¹ééä¸åè° |
| | | selectBatchChange(isSelect, rows, name) { |
| | | rows.forEach((element) => { |
| | | element.loader = true; |
| | | }); |
| | | this.$emit('select-batch-updated', rows, name); |
| | | setTimeout(() => { |
| | | rows.forEach((element) => { |
| | | element.loader = false; |
| | | }); |
| | | }, 1000); |
| | | }, |
| | | /** |
| | | * è¡¨æ ¼æ°æ®æ¥è¯¢ï¼ä¼ é两ç»åæ°ï¼å页信æ¯ååè°å½æ° |
| | | * å页信æ¯å
æ¬å½å页ç currentPageåæ¯é¡µæ°æ®épageSize |
| | | * åè°å½æ°æ¥æ¶ä¸ä¸ªå¯¹è±¡ï¼å
æ¬è¡¨æ ¼æ°æ®æ°ç»dataåæ°æ®æ»æ°total |
| | | */ |
| | | onSearch() { |
| | | this.loading = true; |
| | | this.$emit( |
| | | 'search', |
| | | { |
| | | currentPage: this.currentPage, |
| | | pageSize: this.pageSize |
| | | }, |
| | | (res) => { |
| | | this.tableData = res.data; |
| | | this.total = res.total ? res.total : 0; |
| | | this.loading = false; |
| | | } |
| | | ); |
| | | }, |
| | | calcTableHeight() { |
| | | const h1 = this.$refs.searchRef.$el.offsetHeight; |
| | | const h2 = this.$refs.paginationRef ? this.$refs.paginationRef.$el.offsetHeight : 0; |
| | | const h3 = this.$refs.expandRef.$el.offsetHeight; |
| | | const h4 = this.$refs.expand2Ref.offsetHeight; |
| | | |
| | | const h = h1 + h2 + h3 + h4; |
| | | // return `calc(100vh - ${h1}px - ${h2}px - var(--el-main-padding) * 2 - var(--el-header-height))`; |
| | | return `calc(100vh - ${h}px - 60px - var(--el-main-padding) * 2)`; |
| | | }, |
| | | tableRowClassName({ row }) { |
| | | if (this.rowClassName) { |
| | | if (typeof this.rowClassName == 'string') { |
| | | return this.rowClassName; |
| | | } else if (typeof this.rowClassName == 'function') { |
| | | return this.rowClassName({ row }); |
| | | } |
| | | } else { |
| | | return row.extension1 != '0' ? 'online-row' : 'offline-row'; |
| | | } |
| | | } |
| | | }, |
| | | created() { |
| | | // this.onSearch(); |
| | | }, |
| | | mounted() { |
| | | this.tableHeight = this.calcTableHeight(); |
| | | this.initCols(); |
| | | this.initTableData(); |
| | | this.isOk = true; |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style> |
| | | .l-table .online-row { |
| | | /* background-color: rgb(4, 202, 21); */ |
| | | } |
| | | |
| | | .el-table .offline-row { |
| | | background-color: var(--el-disabled-bg-color); |
| | | color: var(--el-disabled-text-color); |
| | | } |
| | | |
| | | .el-table .cell { |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .el-pagination { |
| | | background-color: var(--el-color-white); |
| | | padding-top: 20px; |
| | | border-top: 1px solid rgba(0, 0, 0, 0.096); |
| | | /* margin-top: 2px; */ |
| | | } |
| | | .no-display { |
| | | display: none; |
| | | } |
| | | .btns { |
| | | margin-left: 10px; |
| | | } |
| | | .flex-div { |
| | | display: flex; |
| | | } |
| | | .loader { |
| | | margin-top: 5px; |
| | | margin-right: 5px; |
| | | border: 4px solid rgba(0, 0, 0, 0.1); /* è½»é¢è²çè¾¹æ¡ */ |
| | | border-radius: 50%; /* åå½¢ */ |
| | | border-top: 4px solid #3498db; /* èè²è¾¹æ¡ */ |
| | | width: 20px; /* å è½½å¨ç宽度 */ |
| | | height: 20px; /* å è½½å¨çé«åº¦ */ |
| | | animation: spin 2s linear infinite; /* æ é循ç¯çæè½¬å¨ç» */ |
| | | } |
| | | .tree-btus { |
| | | margin-left: 24px; |
| | | } |
| | | |
| | | @keyframes spin { |
| | | 0% { |
| | | transform: rotate(0deg); |
| | | } |
| | | 100% { |
| | | transform: rotate(360deg); |
| | | } |
| | | } |
| | | </style> |