From 83efa8f1ebd3ad80dfb5078a10caf9fcc4499dc8 Mon Sep 17 00:00:00 2001 From: shikeying <pxzsky@163.com> Date: 星期一, 08 五月 2023 14:09:50 +0800 Subject: [PATCH] 题库测试页面,涉及组件树 --- src/views/etaa/question_bank/index.vue | 649 +++++++++++++++++++++++++++------------------------------- 1 files changed, 307 insertions(+), 342 deletions(-) diff --git a/src/views/etaa/question_bank/index.vue b/src/views/etaa/question_bank/index.vue index 0b752d5..3928307 100644 --- a/src/views/etaa/question_bank/index.vue +++ b/src/views/etaa/question_bank/index.vue @@ -1,253 +1,166 @@ <template> - <div class="app-container"> + <div class="app-main info-main"> + <el-aside class="sidebar-box" style="padding: 0;"> + <div class="sidebar"> + <el-card class="box-card" shadow="never"> + <div slot="header" class="clearfix"> + <span> + <svg-icon icon-class="nested" style="margin-top: -2px;" />棰樺簱鍒嗙被 + </span> + <el-button style="float: right; padding: 3px 0" type="text" @click="expandedAll">鏀惰捣</el-button> + </div> + <el-input v-model="filterText" clearable placeholder="鍏抽敭瀛楄繃婊�" /> + <el-tree ref="treeRef" :data="treeData" :default-expanded-keys="defaultExpandedKeys" :filter-node-method="filterNode" :props="defaultProps" highlight-current node-key="id" @node-click="handleNodeClick" /> + </el-card> + </div> + </el-aside> - <el-row :gutter="10" class="mb8"> - <el-col :span="6" :xs="24"> - <div class="head-container"> - <el-tree - :data="catalogListOptions" - :props="defaultProps" - :expand-on-click-node="false" - :filter-node-method="filterNode" - ref="tree" - default-expand-all - highlight-current - @node-click="handleNodeClick" - /> + <div class="base-container flex-1"> + <el-card shadow="never" class="box-card"> + <!--鎼滅储鏉′欢--> + <div class="filter-container"> + <el-form :inline="true" :model="filterForm" size="small"> + <el-form-item label="椤剁骇鍗曚綅"> + <el-select v-model="filterForm.orgId" placeholder="閫夋嫨椤剁骇鍗曚綅" @change="search(1)"> + <el-option + v-for="org in this.rootOrgList" :key="org.id" :label="org.dept_name" :value="org.id"/> + </el-select> + </el-form-item> + <el-form-item label="璇曢绫诲瀷"> + <el-select v-model="filterForm.questionType" placeholder="璇曢绫诲瀷"> + <el-option v-for="d in this.questionTypeList" :key="d.key" :label="d.value" :value="d.key"/> + </el-select> + </el-form-item> + <el-form-item label="璇曢棰樼洰"> + <el-input v-model="filterForm.content" placeholder="璇曢鍐呭" clearable/> + </el-form-item> + <el-form-item> + <my-button-v2 site="filter" name="鎼滅储" @click="search(1)" /> + <my-button-v2 site="filter" name="閲嶇疆" @click="reset()" /> + </el-form-item> + </el-form> </div> - </el-col> - <el-col :span="18" :xs="24"> - <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> - <el-form-item label="椤剁骇鍗曚綅" prop="orgId"> - <el-select v-model="queryParams.orgId" placeholder="閫夋嫨椤剁骇鍗曚綅" @change="getList()"> - <el-option - v-for="org in this.rootOrgList" - :key="org.id" - :label="org.dept_name" - :value="org.id" - /> - </el-select> - </el-form-item> + </el-card> - <el-form-item label="璇曢绫诲瀷" prop="questionType"> - <el-select v-model="queryParams.questionType" placeholder="璇曢绫诲瀷"> - <el-option - v-for="d in this.questionTypeList" - :key="d.key" - :label="d.value" - :value="d.key" - /> - </el-select> - </el-form-item> - <el-form-item label="璇曢棰樼洰" prop="content"> - <el-input - v-model="queryParams.content" - placeholder="璇曢鍐呭" - clearable - @keyup.enter.native="handleQuery" - /> - </el-form-item> -<!-- <el-form-item label="涓撲笟鍒嗙被" prop="majorCode">--> -<!-- <el-select v-model="queryParams.majorCode" placeholder="璇烽�夋嫨涓撲笟鍒嗙被" clearable>--> -<!-- <el-option--> -<!-- v-for="dict in dict.type.sys_job_status"--> -<!-- :key="dict.value"--> -<!-- :label="dict.label"--> -<!-- :value="dict.value"--> -<!-- />--> -<!-- </el-select>--> -<!-- </el-form-item>--> - - <el-form-item> - <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button> - <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> - </el-form-item> - </el-form> - - <el-row :gutter="10" class="mb8"> - <el-col :span="1.5"> - <el-button - type="primary" - plain - icon="el-icon-plus" - size="mini" - @click="handleAdd" - v-hasPermi="['exam:online:add']" - >娣诲姞</el-button> - </el-col> - <el-col :span="1.5"> - <el-button - type="danger" - plain - icon="el-icon-delete" - size="mini" - :disabled="multiple" - @click="handleDelete" - v-hasPermi="['exam:online:delBatch']" - >鍒犻櫎</el-button> - </el-col> - <el-col :span="1.5"> - <el-button - type="warning" - plain - icon="el-icon-search" - size="mini" - @click="handleExport" - v-hasPermi="['exam:online:exist']" - >鏌ラ噸</el-button> - </el-col> - <el-col :span="1.5"> - <el-button - type="warning" - plain - icon="el-icon-upload2" - size="mini" - @click="handleExport" - v-hasPermi="['exam:online:upload']" - >瀵煎叆</el-button> - </el-col> - <el-col :span="1.5"> - <el-button - type="info" - plain - icon="el-icon-download" - size="mini" - @click="" - v-hasPermi="['exam:online:download']" - >妯℃澘涓嬭浇</el-button> - </el-col> - <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> - </el-row> - - <el-table v-loading="loading" :data="examList" @selection-change="handleSelectionChange"> - <el-table-column type="selection" width="55" align="left" /> - <el-table-column label="ID" align="left" prop="id" :show-overflow-tooltip="true" /> - <el-table-column label="褰掑睘" align="left" prop="parameter.orgName"/> - <el-table-column label="澶х被" align="left" prop="parameter.rootCatalogName"/> - <el-table-column label="瀛愬垎绫�" align="left" prop="parameter.majorCatalogName"/> - <el-table-column label="棰樼洰" align="left" prop="content" :show-overflow-tooltip="true" /> - <el-table-column label="璇曢绫诲瀷" align="left" prop="parameter.questionTypeName"/> - <el-table-column label="鍒涘缓浜�" align="left" prop="createUserId" :show-overflow-tooltip="true" /> - <el-table-column label="鍒涘缓鏃堕棿" align="left" prop="parameter.createTimeName" /> - <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> - <template slot-scope="scope"> - <el-button - size="mini" - type="text" - icon="el-icon-edit" - @click="handleUpdate(scope.row)" - v-hasPermi="['exam:online:edit']" - >淇敼</el-button> - <el-button - size="mini" - type="text" - icon="el-icon-delete" - @click="handleDelete(scope.row)" - v-hasPermi="['exam:online:del']" - >鍒犻櫎</el-button> - </template> - </el-table-column> - </el-table> - - <pagination - v-show="total>0" - :total="total" - :page.sync="queryParams.pageNum" - :limit.sync="queryParams.pageSize" - @pagination="getList" - /> - </el-col> - </el-row> - - <!-- 娣诲姞鎴栦慨鏀瑰畾鏃朵换鍔″璇濇 --> - <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body> - <el-form ref="form" :model="form" :rules="rules" label-width="120px"> - <el-row> - <el-col :span="24"> - <el-form-item label="鎵�灞炲垎绫�" prop="majorId"> - <el-select v-model="form.majorId" placeholder="璇烽�夋嫨鎵�灞炲垎绫�"> - <el-option - v-for="dict in dict.type.sys_job_group" - :key="dict.value" - :label="dict.label" - :value="dict.value" - ></el-option> - </el-select> - </el-form-item> - </el-col> - <el-col :span="24"> - <el-form-item label="棰樼洰绫诲瀷" prop="type"> - <el-select v-model="form.type" placeholder="璇烽�夋嫨棰樼洰绫诲瀷"> - <el-option - v-for="dict in dict.type.sys_job_group" - :key="dict.value" - :label="dict.label" - :value="dict.value" - ></el-option> - </el-select> - </el-form-item> - </el-col> - <el-col :span="24"> - <el-form-item label="棰樼洰" prop="content"> - <el-input v-model="form.content" placeholder="璇疯緭鍏ラ鐩�"/> - </el-form-item> - </el-col> - </el-row> - </el-form> - <div slot="footer" class="dialog-footer"> - <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> - <el-button @click="cancel">鍙� 娑�</el-button> - </div> - </el-dialog> - - <!-- 璇曢搴撹缁� --> - <el-dialog title="璇曢搴撹缁�" :visible.sync="openView" width="700px" append-to-body> - <el-form ref="form" :model="form" label-width="120px" size="mini"> - <el-row> - <el-col :span="12"> - <el-form-item label="鎵�灞炲垎绫伙細">{{ form.id }}</el-form-item> - <el-form-item label="棰樼洰绫诲瀷锛�">{{ form.jobName }}</el-form-item> - </el-col> - <el-col :span="12"> - <el-form-item label="棰樼洰锛�">{{ "" }}</el-form-item> - <el-form-item label="绛旀锛�">{{ form.createTime }}</el-form-item> - </el-col> - </el-row> - </el-form> - <div slot="footer" class="dialog-footer"> - <el-button @click="openView = false">鍏� 闂�</el-button> - </div> - </el-dialog> + <!--鍒楄〃--> + <my-table-v3 ref="myTable" :filter="filterForm" :table="table" /> + </div> + <!--娣诲姞/缂栬緫寮圭獥--> + <add v-if="editSetting.show" :setting="editSetting" @search="search()" @close="editSetting.show=false"/> + <!-- 瀵煎叆绐楀彛--> + <my-import :import-setting="importSetting" :dialog-show="importSetting.dialogShow" :dialog-title="importSetting.dialogTitle"/> </div> </template> <script> - // import { listJob, getJob, delJob, addJob, updateJob, runJob, changeJobStatus } from "@/api/monitor/job"; - import { listOrgRoot, listOrgRootTree } from '@/api/system/dept' - import { listCatalogTreeList, listQuestion, listQuestionType } from '@/api/etaa/question_bank' + import { getToken } from '@/utils/auth' + import {listOrgRoot} from '@/api/system/dept' + import {clear, listCatalogTreeList, listQuestionType} from '@/api/etaa/question_bank' + import myTableV3 from '@/views/components/myTableV3'; + import myButtonV2 from '@/views/components/myButtonV2' + import myImport from '@/views/components/myImport' + import {isEmptyValue} from "@/utils/StringUtils"; + import add from './add' export default { - // components: { Crontab }, + components: {myTableV3, myButtonV2, add, myImport}, name: "questionBank", - dicts: ['sys_job_status'], data() { return { - // 鏃ユ湡鑼冨洿 - dateRange: [], - // 閬僵灞� - loading: true, - // 閫変腑鏁扮粍 - ids: [], - // 闈炲崟涓鐢� - single: true, - // 闈炲涓鐢� - multiple: true, - // 鏄剧ず鎼滅储鏉′欢 - showSearch: true, - // 鎬绘潯鏁� - total: 0, - // 琛ㄦ牸鏁版嵁 - examList: [], + /** 鏍戦厤缃�*/ + defaultExpandedKeys: [1], // 榛樿灞曞紑鐨刱ey + filterText: '', + treeData: [], + /** 鍒嗙被鏍戞暟鎹粨鏋� */ + defaultProps: { + children: "children", + label: "label" + }, + + /** 鎼滅储鏉′欢*/ + filterForm: { + orgId: null, + questionType: null, + content: null + }, + + table: { + // size: "small", + autoLoad: false, + showIndex: false, // 鏄惁鏄剧ず搴忓彿 + expand: false, // 鏄惁鏄剧ず璇︽儏鏁版嵁 + checkBox: false, // 鏄惁鏄剧ず澶嶉�夋 + url: globalConf.baseUrl + '/etaa/question_bank/list', // 璇锋眰鍦板潃 + // 宸ュ叿鏉� + tools: { + columnsCtrl: {// 鍒楁帶鍒舵寜閽� + show: true + }, + generalExport: {// 閫氱敤瀵煎嚭鎸夐挳 + show: false + }, + custom: [ // 鑷畾涔夊伐鍏锋潯鎸夐挳 + { + name: '娣诲姞璇曢', + // checkPermission: 'system:config:remove', + // myType: 'danger', + mySize: 'mini', + click: ()=> { + this.handleAdd(); + } + }, + { + name: '瀵煎叆', + click: ()=> { + this.handleImport(); + } + }, + { + name: '娓呯┖棰樺簱', + checkPermission: 'etaa:question_bank:clear', + myType: 'info', + mySize: 'mini', + click: ()=> { + this.handleClear(); + } + } + ] + }, + columns: [ + { title: 'ID', field: 'id', align: 'left', width: 80 }, + { title: '褰掑睘', field: 'parameter.orgName', align: 'left', width: 130 }, + { title: '澶х被', field: 'parameter.rootCatalogName', align: 'left', width: 150 }, + { title: '瀛愬垎绫�', field: 'parameter.majorCatalogName', align: 'left', width: 160}, + { title: '棰樼洰', field: 'content', align: 'left', width: 230 }, + { title: '棰樺瀷', field: 'parameter.questionTypeName', align: 'left', width: 80 }, + { title: '鍒涘缓浜�', field: 'createUserId', align: 'left', width: 80 }, + { title: '鍒涘缓鏃堕棿', field: 'parameter.createTimeName', align: 'left', width: 160 } + ], + // 鎿嶄綔淇℃伅 + operation: { + show: true, // 鏄剧ず鎿嶄綔鍒� + width: '100', // 鍒楀 + attr: [ + { + title: '缂栬緫', + checkPermission: 'system:config:edit', + events: row => { + this.handleUpdate(row) + } + } + ] + }, + paging: { + show: true, // 鏄剧ず鍒嗛〉 + // 鍒嗛〉淇℃伅 + page: { + small: false, + pageNum: 1, + pageSize: platformPageSize, + total: 0 + } + } + }, // 2022-12-30 鏍规満鏋勫垪琛紝涓汉鍙兘鍒楀嚭鑷繁鎵�鍦ㄦ牴鏈烘瀯 rootOrgList:[], @@ -255,48 +168,81 @@ selectedRootOrgId: undefined, // 璇曢绫诲埆鍒楄〃锛�2023-03-11 questionTypeList: [], - // 2023-03-13 璇曢绫诲埆鏍戞暟鎹�夐」 - catalogListOptions: undefined, - /** 鍒嗙被鏍戞暟鎹粨鏋� */ - defaultProps: { - children: "children", - label: "label" + + // 娣诲姞&缂栬緫绐楀彛 + editSetting: { + id: null, + title: '', + show: false }, - // 寮瑰嚭灞傛爣棰� - title: "", - // 鏄惁鏄剧ず寮瑰嚭灞� - open: false, - // 鏄惁鏄剧ず璇︾粏寮瑰嚭灞� - openView: false, - // 鏄惁鏄剧ずCron琛ㄨ揪寮忓脊鍑哄眰 - openCron: false, - // 浼犲叆鐨勮〃杈惧紡 - expression: "", - // 鏌ヨ鍙傛暟 - queryParams: { - pageNum: 1, - pageSize: 10, - content: undefined, - catalogId: undefined, - orgId: undefined, - questionType: undefined + // 瀵煎叆 + importSetting: { + dialogTitle: '瀵煎叆', + dialogShow: false, + fileSettings: { + uploadUrl: globalConf.baseUrl + "/etaa/question_bank/select/import?Authorization=" + getToken(), // 涓婁紶鍦板潃 + accept: '.xlsx,.csv', // 鏍煎紡 + type: 'text', // 鍥炴樉褰㈠紡 + loading: false // 瀵煎叆鏁堟灉 + }, + /* 妯℃澘涓嬭浇 */ + templateSettings: { + templateName: '棰樺簱瀵煎叆妯℃澘.xlsx', // 鍚嶇О + templateUrl: globalConf.baseUrl + '/etaa/question_bank/select/downloadTemplate?Authorization=' + getToken() // 涓嬭浇鍦板潃 + }, + onSuccess: null }, - // 琛ㄥ崟鍙傛暟 - form: {}, - // 琛ㄥ崟鏍¢獙 - rules: { - content: [ - { required: true, message: "棰樼洰涓嶈兘涓虹┖", trigger: "blur" } - ] - } }; }, + created() { this.getRootOrgList(); this.getQuestionTypeList(); }, methods: { + // 鏍戣妭鐐硅繃婊� + filterNode(value, data) { + if (!value) return true; + console.log("value = " + value + ", data = " + data); + return data.label.indexOf(value) !== -1; + }, + // 鏍戣妭鐐规敹璧� + expandedAll() { + const nodes = this.$refs.treeRef.store._getAllNodes() + for (let i = 0; i < nodes.length; i++) { + nodes[i].expanded = false + } + // 缂栬緫椤甸潰 + // this.editSetting.orgId = null + // this.editSetting.orgName = '鏃�' + this.reset() + }, + + // 閲嶇疆 + reset() { + this.filterForm = { + orgId: this.selectedRootOrgId, + questionType: null, + content: null + } + this.search(1) + }, + + // 鏌ヨtable鍒楄〃 + search(pageNum) { + if(isEmptyValue(this.filterForm.orgId)){ + return; + } else { + // console.log("-----------" + this.filterForm.orgId); + if (pageNum != undefined) { + this.$refs.myTable.search({ pageNum: pageNum }) + } else { + this.$refs.myTable.search() + } + } + }, + /** 鑾峰彇璇曢绫诲埆闆嗗悎 2023-03-11 */ getQuestionTypeList(){ listQuestionType().then(response => { @@ -306,95 +252,33 @@ }, /** 鑾峰彇椤剁骇鏈烘瀯鍒楄〃閫夋嫨妗� 2022-12-30 */ getRootOrgList(){ - this.loading = true; listOrgRoot().then(response => { this.rootOrgList = response.data; this.selectedRootOrgId = this.rootOrgList[0].id; - this.queryParams.orgId = this.selectedRootOrgId; - this.loading = false; + this.filterForm.orgId = this.selectedRootOrgId; }).then(() => { this.listCatalogTree(); - this.getList(); + this.search(1); }).catch(function() { - this.loading = false; }); }, // 璇曢绫诲埆鏍� listCatalogTree(){ listCatalogTreeList("question_root_catalog").then(response => { - console.log(response.data); - this.catalogListOptions = response.data; + // console.log(response.data); + this.treeData = response.data; }); }, - /** 鏌ヨ鍒楄〃 */ - getList() { - this.loading = true; - listQuestion(this.queryParams).then(response => { - this.examList = response.data; - this.total = response.total; - this.loading = false; - }); - }, - - // 绛涢�夎妭鐐� - filterNode(value, data) { - if (!value) return true; - console.log("value = " + value + ", data = " + data); - return data.label.indexOf(value) !== -1; - }, // 鑺傜偣鍗曞嚮浜嬩欢 handleNodeClick(data) { - this.queryParams.catalogId = data.id; - this.handleQuery(); + // 淇濇寔宸插睍寮�鐨勮彍鍗曞埛鏂板悗渚濇棫灞曞紑 + this.defaultExpandedKeys = [data.id]; + this.filterForm.catalogId = data.id; + this.search(1); }, - // 鍙栨秷鎸夐挳 - cancel() { - this.open = false; - this.reset(); - }, - // 琛ㄥ崟閲嶇疆 - reset() { - this.form = { - id: undefined, - content: undefined, - concurrent: 1, - status: "0" - }; - this.dateRange = [];// 鏃堕棿鑼冨洿 - this.resetForm("form"); - }, - /** 鎼滅储鎸夐挳鎿嶄綔 */ - handleQuery() { - this.queryParams.pageNum = 1; - this.getList(); - }, - /** 閲嶇疆鎸夐挳鎿嶄綔 */ - resetQuery() { - this.resetForm("queryForm"); - this.queryParams.orgId = this.selectedRootOrgId; - this.queryParams.questionType = undefined; - this.handleQuery(); - }, - // 澶氶�夋閫変腑鏁版嵁 - handleSelectionChange(selection) { - this.ids = selection.map(item => item.id); - this.single = selection.length != 1; - this.multiple = !selection.length; - }, - // 鐘舵�佷慨鏀� - handleStatusChange(row) { - let text = row.status === "0" ? "鍚敤" : "鍋滅敤"; - this.$modal.confirm('纭瑕�"' + text + '""' + row.name + '"浠诲姟鍚楋紵').then(function() { - return changeJobStatus(row.id, row.status); - }).then(() => { - this.$modal.msgSuccess(text + "鎴愬姛"); - }).catch(function() { - row.status = row.status === "0" ? "1" : "0"; - }); - }, /** 浠诲姟璇︾粏淇℃伅 */ handleView(row) { // getJob(row.id).then(response => { @@ -404,10 +288,21 @@ }, /** 鏂板鎸夐挳鎿嶄綔 */ handleAdd() { - this.reset(); - this.open = true; - this.title = "娣诲姞璇曢搴�"; + if(isEmptyValue(this.selectedRootOrgId)){ + this.$message.warning("璇峰厛閫夋嫨涓�涓《绾ф満鏋�"); + return; + } + if(isEmptyValue(this.filterForm.catalogId)){ + this.$message.warning("璇峰厛閫夋嫨棰樺簱鍒嗙被"); + return; + } + this.editSetting.id = null; + this.editSetting.title = "娣诲姞璇曢"; + this.editSetting.catalogId = this.filterForm.catalogId; + this.editSetting.orgId = this.selectedRootOrgId; + this.editSetting.show = true; }, + /** 淇敼鎸夐挳鎿嶄綔 */ handleUpdate(row) { this.reset(); @@ -418,6 +313,65 @@ this.title = "淇敼璇曢搴�"; }); }, + + handleClear(){ + this.$modal.confirm('瑕佹竻绌洪搴撳悧锛熼�氬父鍙湁娴嬭瘯闃舵闇�瑕佷娇鐢�!').then(function() { + return clear(); + }).then(() => { + this.search(1); + this.$modal.msgSuccess("鎿嶄綔鎴愬姛"); + }).catch(() => {}); + }, + + handleImport(){ + this.importSetting.dialogShow = true + this.importSetting.onSuccess = (response, callBack) => { + console.log(response); + if(response.code != 1){ + this.$message.error('瀵煎叆澶辫触' || response.msg); + callBack(); + return; + } + + if(isEmptyValue(response.data)){ + // 娌℃湁杩斿洖閿欒璁板綍鏂囦欢 + this.$message.success("瀵煎叆鎴愬姛"); + this.search(); + callBack(); + return; + } + + this.$confirm("璇锋煡鐪嬪鍏ラ敊璇紝鏂囦欢:" + response.data, '瀵煎叆瀹屾垚', { + confirmButtonText: '纭畾', + type: 'warning' + }).then(() => { + this.search() + }); + // user.importUser(response.data[0]).then(response => { + // if (response.code === 10000) { + // this.importSetting.dialogShow = false + // if (response.data.errorInfo.length === 0) { + // this.$message.success(response.data.info) + // this.search() + // } else { + // const errorInfoList = response.data.errorInfo + // var errorInfo = errorInfoList.join('') + // this.$confirm(errorInfo, '鎻愮ず', { + // confirmButtonText: '纭畾', + // type: 'warning' + // }).then(() => { + // this.search() + // }) + // } + // } else { + // this.$message.error('瀵煎叆澶辫触' || response.description) + // this.search() + // } + // callBack() + // }) + } + }, + /** 鎻愪氦鎸夐挳 */ submitForm: function() { this.$refs["form"].validate(valid => { @@ -457,3 +411,14 @@ } }; </script> +<style scope lang="scss"> + .info-main{ + display:-webkit-box; + display: -moz-box; + display: -0-box; + min-height: calc( 100vh - 50px); + } + .flex-1{ + flex:1; + } +</style> -- Gitblit v1.9.1