IndicatorSetting.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  1. <template>
  2. <div class="all">
  3. <div class="create-methods flex-box-ce">
  4. <div class="flex-box-ce">
  5. <div class="method-item" v-for="(item, index) in methods"
  6. :class="currentIndex === index ? 'active' : ''" :key="item.id"
  7. @click="changeMethod(item.id, index)">
  8. {{ item.title }}
  9. </div>
  10. </div>
  11. <el-tooltip effect="dark" content="教程指引" placement="top">
  12. <div class="icon flex-center-center" @click="initStepData()">
  13. <i class="el-icon-document"></i>
  14. </div>
  15. </el-tooltip>
  16. </div>
  17. <div class="setting-content flex-1" v-if="method == 1">
  18. <UploadPublish2 ref="UploadPublish2" />
  19. </div>
  20. <div class="setting-content flex-1" v-if="method == 2">
  21. <UploadPublish />
  22. </div>
  23. <el-dialog :visible.sync="dialogVisible" title="已创建的指标库" center width="600px">
  24. <div class="dialog-content">
  25. <template v-if="templateList.length > 0">
  26. <div class="flex-box-ce template-item" v-for="(item, index) in templateList" :key="index">
  27. <div class="flex-box flex-1" @click="chooseTemplate(item)">
  28. <div style="width: 20px;"><i class="el-icon-tickets blue"></i></div>
  29. <span class="message-content">{{ item.title || '默认标题' }}</span>
  30. </div>
  31. <div>
  32. <el-popconfirm confirm-button-text='确定' cancel-button-text='不用了' icon="el-icon-info"
  33. icon-color="red" title="确定删除这个考核模板吗?" @confirm="confirmDelete(item.templateId)"
  34. @cancel="cancelDelete()">
  35. <el-link slot="reference" type="danger">删除</el-link>
  36. </el-popconfirm>
  37. </div>
  38. </div>
  39. </template>
  40. <noData v-else content="暂无内容" imgW="120px" imgH="120px"></noData>
  41. </div>
  42. </el-dialog>
  43. </div>
  44. </template>
  45. <script>
  46. import { mapGetters } from 'vuex';
  47. import TemplateDetails from './IndicatorSetting/TemplateDetails.vue';
  48. import PublishComp from './IndicatorSetting/PublishComp.vue';
  49. import TemplateMixedPublish from './IndicatorSetting/TemplateMixedPublish.vue';
  50. import UploadPublish from './IndicatorSetting/UploadPublish.vue';
  51. import UploadPublish2 from './IndicatorSetting/UploadPublish2.vue';
  52. import indicatorSettingStep from "@/newPerformance/utils/indicatorSettingStep"
  53. import introJs from 'intro.js'
  54. import 'intro.js/introjs.css'
  55. export default {
  56. components: {
  57. TemplateDetails,
  58. PublishComp,
  59. TemplateMixedPublish,
  60. UploadPublish,
  61. UploadPublish2
  62. },
  63. data() {
  64. return {
  65. dialogVisible: false,
  66. currentIndex: 0,
  67. methods: [
  68. // { id: 0, title: "方式1:手动创建指标" },
  69. { id: 1, title: "方式1:快速创建" },
  70. { id: 2, title: "方式2:批量导入指标" },
  71. ],
  72. method: 1,
  73. loading: false,
  74. templateList: [],
  75. step: 0,
  76. activeIndex: 1,
  77. templateId: "",
  78. }
  79. },
  80. watch: {
  81. step(v) {
  82. this.activeIndex = v + 1
  83. }
  84. },
  85. computed: {
  86. ...mapGetters(['user_info'])
  87. },
  88. mounted() {
  89. this.$nextTick(() => {
  90. if (!localStorage.getItem("isLearned")) {
  91. this.startGuide()
  92. }
  93. })
  94. },
  95. created() {
  96. },
  97. methods: {
  98. startGuide() {
  99. introJs().setOptions({
  100. nextLabel: '下一个', // 下一个按钮文字
  101. prevLabel: '上一个', // 上一个按钮文字
  102. skipLabel: '跳过', // 跳过按钮文字
  103. doneLabel: '立即体验',// 完成按钮文字
  104. tooltipClass: 'intro-tooltip', /* 引导说明文本框的样式 */
  105. highlightClass: 'intro-highlight', /* 说明高亮区域的样式 */
  106. exitOnEsc: true, /* 是否使用键盘Esc退出 */
  107. exitOnOverlayClick: false, /* 是否允许点击空白处退出 */
  108. keyboardNavigation: true, /* 是否允许键盘来操作 */
  109. showBullets: false, /* 是否使用点显示进度 */
  110. showProgress: false, /* 是否显示进度条 */
  111. scrollToElement: true, /* 是否滑动到高亮的区域 */
  112. overlayOpacity: 0.5, // 遮罩层的透明度 0-1之间
  113. positionPrecedence: ['bottom', 'top', 'right', 'left'], /* 当位置选择自动的时候,位置排列的优先级 */
  114. disableInteraction: false, /* 是否禁止与元素的相互关联 */
  115. hidePrev: true, /* 是否在第一步隐藏上一步 */
  116. hidePrev: false, // 在第一步中是否隐藏上一个按钮
  117. hideNext: false, // 在最后一步中是否隐藏下一个按钮
  118. exitOnOverlayClick: false, // 点击叠加层时是否退出介绍
  119. showStepNumbers: false, // 是否显示红色圆圈的步骤编号
  120. disableInteraction: true, // 是否禁用与突出显示的框内的元素的交互,就是禁止点击
  121. showBullets: true, // 是否显示面板指示点
  122. // 配置内容 steps数组,内部一个对象代表一个步骤
  123. steps: indicatorSettingStep
  124. }).onbeforechange((e) => {
  125. console.log(e)
  126. // if (e.className.includes("choose-btn")) {
  127. // this.$refs.UploadPublish2.openTemplate()
  128. // }
  129. }).oncomplete(function () {
  130. //点击跳过按钮后执行的事件
  131. localStorage.setItem("isLearned", true)
  132. }).onexit(function () {
  133. //点击结束按钮后, 执行的事件
  134. localStorage.setItem("isLearned", true)
  135. }).start()
  136. },
  137. // 开启教程指引
  138. initStepData() {
  139. setTimeout(() => {
  140. this.startGuide();
  141. }, 300)
  142. },
  143. changeMethod(id, index) {
  144. this.method = id;
  145. this.currentIndex = index;
  146. },
  147. chooseTemplate(item) {
  148. this.templateId = item.templateId
  149. this.step = 1;
  150. this.dialogVisible = false;
  151. },
  152. getTemplateList() {
  153. this.$axiosUser("get", `/performance/template/list/self/${this.user_info.site_id}`).then(res => {
  154. this.templateList = res.data.data.list;
  155. })
  156. },
  157. addTemplate() {
  158. this.$axiosUser('post', `/performance/template/create/${this.user_info.site_id}`).then(res => {
  159. let { data: { data, code } } = res
  160. if (code == 1) {
  161. this.$axiosUser("get", `/performance/template/list/self/${this.user_info.site_id}`).then(res => {
  162. this.templateList = res.data.data.list
  163. this.templateId = this.templateList[this.templateList.length - 1].templateId;
  164. this.$message.success("创建成功")
  165. this.step = 1;
  166. })
  167. }
  168. });
  169. },
  170. // 确认删除模板
  171. confirmDelete(templateId) {
  172. this.$axiosUser('post', `/performance/template/remove/${this.user_info.site_id}/${templateId}`).then(res => {
  173. this.$axiosUser("get", `/performance/template/list/self/${this.user_info.site_id}`).then(res => {
  174. this.templateList = res.data.data.list
  175. })
  176. })
  177. },
  178. cancelDelete() {
  179. console.log("取消删除");
  180. },
  181. prevStep() {
  182. if (this.step <= 0) return;
  183. this.step--;
  184. },
  185. nextStep() {
  186. if (this.step >= 2) return;
  187. this.step++;
  188. },
  189. // 发布考核弹框的回调
  190. onPubishConfirm(params, selectOkrs) {
  191. let templateId = this.templateId;
  192. let { title, startDate, endDate, cycleType, employeeIds, okrs, cateId } = params
  193. let employees = employeeIds.map(employee => ({
  194. employeeId: employee,
  195. ids: [],
  196. interviewFlow: {
  197. nodes: [
  198. {
  199. id: "IT_1894283564934688769",
  200. type: "interview",
  201. allows: [],
  202. enable: false,
  203. weight: 0,
  204. children: [],
  205. assigneeIds: [],
  206. leaderLevel: 1,
  207. assigneeType: "self",
  208. multipleType: "or"
  209. }
  210. ]
  211. }
  212. }))
  213. let requireParams = {
  214. title,
  215. cycleType,
  216. startDate,
  217. endDate,
  218. okrs,
  219. templates: [
  220. {
  221. templateId,
  222. employees
  223. }
  224. ],
  225. cateId
  226. }
  227. // let url = `/performance/review/publish/${this.user_info.site_id}`;
  228. // console.log(requireParams)
  229. let url = `/performance/review/publish/templates/${this.user_info.site_id}`;
  230. this.loading = true
  231. this.$http.post(url, requireParams).then(res => {
  232. console.log(res)
  233. let { data, code, message } = res
  234. this.loading = false
  235. if (code == 1) {
  236. this.$message.success("发布成功");
  237. this.$emit("changeCurrentId", {currentId: '1'})
  238. setTimeout(() => {
  239. this.$router.push("newPerformance")
  240. }, 1000);
  241. } else {
  242. this.$message.error(message || '发布失败');
  243. }
  244. })
  245. },
  246. activeStep(index, flag = true) {
  247. this.activeIndex = index;
  248. if (flag) this.step = index - 1;
  249. },
  250. changeStep(step) {
  251. this.activeIndex = step + 1;
  252. }
  253. }
  254. }
  255. </script>
  256. <style lang="scss">
  257. .introjs-helperLayer {
  258. box-shadow: rgba(33, 33, 33, 0.8) 0px 0px 1px 0px, rgba(33, 33, 33, 0.5) 0px 0px 0px 5000px !important;
  259. border: 3px dashed #409eff;
  260. }
  261. /* 调整 intro.js 弹出框的大小 */
  262. .introjs-tooltip {
  263. width: auto;
  264. /* 自动调整宽度 */
  265. max-width: 1600px;
  266. /* 最大宽度 */
  267. height: auto;
  268. /* 自动调整高度 */
  269. overflow: hidden;
  270. /* 防止内容溢出 */
  271. }
  272. .new-tips {
  273. color: #409eff;
  274. line-height: 80px;
  275. cursor: pointer;
  276. }
  277. .introjs-tooltip-title {
  278. font-size: 16px;
  279. width: 80%;
  280. padding-top: 10px;
  281. }
  282. .warper {
  283. width: 200px;
  284. height: 100px;
  285. line-height: 100px;
  286. text-align: center;
  287. border: 1px solid saddlebrown;
  288. }
  289. /* 重置引导组件样式(类似element-ui个人使用) */
  290. .intro-tooltip {
  291. color: #ffff;
  292. background: #2c3e50;
  293. }
  294. /* 引导提示框的位置 */
  295. .introjs-bottom-left-aligned {
  296. left: 45% !important;
  297. }
  298. .introjs-right,
  299. .introjs-left {
  300. top: 30%;
  301. }
  302. .intro-highlight {
  303. background: rgba(255, 255, 255, 0.5);
  304. }
  305. .introjs-arrow.left {
  306. border-right-color: #2c3e50;
  307. }
  308. .introjs-arrow.top {
  309. border-bottom-color: #2c3e50;
  310. }
  311. .introjs-arrow.right {
  312. border-left-color: #2c3e50;
  313. }
  314. .introjs-arrow.bottom {
  315. border-top-color: #2c3e50;
  316. }
  317. /* 提示框头部区域 */
  318. .introjs-tooltip-header {
  319. padding-right: 0 !important;
  320. padding-top: 0 !important;
  321. }
  322. .introjs-skipbutton {
  323. color: #409eff !important;
  324. font-size: 14px !important;
  325. font-weight: normal !important;
  326. // padding: 8px 10px !important ;
  327. }
  328. .introjs-tooltipbuttons {
  329. border: none !important;
  330. }
  331. .introjs-tooltiptext {
  332. font-size: 14px !important;
  333. padding: 15px !important;
  334. }
  335. /* 提示框按钮 */
  336. .introjs-tooltipbuttons {
  337. display: flex;
  338. align-items: center;
  339. justify-content: center;
  340. }
  341. .introjs-button {
  342. width: 50px !important;
  343. text-align: center;
  344. padding: 4px !important;
  345. font-size: 12px !important;
  346. font-weight: 500 !important;
  347. border-radius: 3px !important;
  348. border: none !important;
  349. }
  350. .introjs-button:last-child {
  351. margin-left: 10px;
  352. }
  353. .introjs-prevbutton {
  354. color: #606266 !important;
  355. background: #fff !important;
  356. border: 1px solid #dcdfe6 !important;
  357. }
  358. .introjs-nextbutton {
  359. color: #fff !important;
  360. background-color: #409eff !important;
  361. border-color: #409eff !important;
  362. }
  363. .introjs-disabled {
  364. color: #9e9e9e !important;
  365. border-color: #bdbdbd !important;
  366. background-color: #f4f4f4 !important;
  367. }
  368. </style>
  369. <style scoped lang="scss">
  370. .dialog-content {
  371. width: 100%;
  372. height: 500px;
  373. overflow-y: auto;
  374. padding-bottom: 20px;
  375. box-sizing: border-box;
  376. .template-item {
  377. padding: 5px;
  378. box-sizing: border-box;
  379. transition: all 0.3s;
  380. &:hover {
  381. cursor: pointer;
  382. background: #f7f7f7;
  383. }
  384. }
  385. /* 设置滚动条的宽度和背景色 */
  386. &::-webkit-scrollbar {
  387. width: 6px;
  388. height: 6px;
  389. background-color: #f9f9f9;
  390. }
  391. /* 设置滚动条滑块的样式 */
  392. &::-webkit-scrollbar-thumb {
  393. border-radius: 6px;
  394. background-color: #c1c1c1;
  395. }
  396. /* 设置滚动条滑块hover样式 */
  397. &::-webkit-scrollbar-thumb:hover {
  398. background-color: #a8a8a8;
  399. }
  400. /* 设置滚动条轨道的样式 */
  401. &::-webkit-scrollbar-track {
  402. box-shadow: inset 0 0 5px rgba(87, 175, 187, 0.1);
  403. border-radius: 6px;
  404. background: #ededed;
  405. }
  406. }
  407. .all {
  408. width: 100%;
  409. height: 100%;
  410. position: relative;
  411. border-radius: 5px;
  412. display: flex;
  413. flex-direction: column;
  414. .create-methods {
  415. background: #fff;
  416. padding: 10px;
  417. box-sizing: border-box;
  418. justify-content: space-between;
  419. .method-item {
  420. padding: 15px;
  421. border-radius: 4px;
  422. border: 1px solid #ebebeb;
  423. font-size: 14px;
  424. width: 200px;
  425. color: #222;
  426. margin-right: 12px;
  427. cursor: pointer;
  428. box-sizing: border-box;
  429. &:hover {
  430. background-color: #f5f7fa;
  431. }
  432. }
  433. .active {
  434. background-color: #f5f7fa;
  435. color: #409EFF;
  436. }
  437. .icon {
  438. width: 40px;
  439. height: 40px;
  440. border: 1px solid #ccc;
  441. border-radius: 50%;
  442. font-size: 20px;
  443. color: #999;
  444. display: flex;
  445. align-items: center;
  446. justify-content: center;
  447. transition: all 0.3s;
  448. &:hover {
  449. cursor: pointer;
  450. background: #f5f5f5;
  451. }
  452. }
  453. }
  454. .setting-content {
  455. margin: 10px 0;
  456. background: #fff;
  457. padding: 10px;
  458. box-sizing: border-box;
  459. border-radius: 5px;
  460. display: flex;
  461. flex-direction: column;
  462. position: relative;
  463. overflow: hidden;
  464. .operation-box {
  465. border: 1px solid #eee;
  466. padding: 10px;
  467. box-sizing: border-box;
  468. border-radius: 5px;
  469. overflow-y: auto;
  470. /* 设置滚动条的宽度和背景色 */
  471. &::-webkit-scrollbar {
  472. width: 6px;
  473. height: 6px;
  474. background-color: #f9f9f9;
  475. }
  476. /* 设置滚动条滑块的样式 */
  477. &::-webkit-scrollbar-thumb {
  478. border-radius: 6px;
  479. background-color: #c1c1c1;
  480. }
  481. /* 设置滚动条滑块hover样式 */
  482. &::-webkit-scrollbar-thumb:hover {
  483. background-color: #a8a8a8;
  484. }
  485. /* 设置滚动条轨道的样式 */
  486. &::-webkit-scrollbar-track {
  487. box-shadow: inset 0 0 5px rgba(87, 175, 187, 0.1);
  488. border-radius: 6px;
  489. background: #ededed;
  490. }
  491. }
  492. }
  493. }
  494. .step-item2 {
  495. padding: 0 10px;
  496. color: #d6d6d6;
  497. text-align: center;
  498. height: 60px;
  499. cursor: pointer;
  500. position: relative;
  501. }
  502. .step-item2 span {
  503. width: 36px;
  504. height: 36px;
  505. border-radius: 50%;
  506. text-align: center;
  507. line-height: 28px;
  508. font-size: 20px;
  509. border: 4px solid #d6d6d6;
  510. }
  511. .step-item2 div {
  512. font-size: 14px;
  513. margin-left: 5px;
  514. }
  515. .active-step2 span {
  516. border: 4px solid #409EFF;
  517. color: #fff;
  518. background-color: #409EFF;
  519. }
  520. .active-step2 div {
  521. color: #409EFF;
  522. }
  523. .barder-a::before {
  524. position: absolute;
  525. content: ' ';
  526. height: 4px;
  527. width: 120px;
  528. top: 28px;
  529. background-color: #d6d6d6;
  530. border-radius: 3px;
  531. right: -60px;
  532. }
  533. .step-item {
  534. width: 140px;
  535. color: #777777;
  536. text-align: center;
  537. height: 60px;
  538. cursor: pointer;
  539. }
  540. .step-item span {
  541. width: 24px;
  542. height: 24px;
  543. border-radius: 50%;
  544. text-align: center;
  545. line-height: 24px;
  546. border: 1px solid #ebebeb;
  547. margin-right: 10px;
  548. }
  549. .active-step {
  550. background-color: #1583f2;
  551. color: #fff;
  552. }
  553. .active-step span {
  554. border: 1px solid #1583f2;
  555. background-color: #fff;
  556. color: #1583f2;
  557. }
  558. </style>