kpi-formula-editor.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784
  1. <template>
  2. <div :id="$style.formulaPage">
  3. <!-- 公式编辑区域 -->
  4. <div
  5. :id="$style.formulaView"
  6. ref="formulaView"
  7. :class="$style.formulaView"
  8. @click.stop="recordPosition"
  9. >
  10. <div
  11. v-for="(item, index) in formulaList"
  12. :key="index"
  13. :class="$style.contentItem"
  14. @click.stop="recordPosition(index)"
  15. >
  16. <div v-if="item.type === 'placeholder'" :class="$style.placeholder"> &zwj;</div>
  17. <div v-if="item.type === 'num'" :class="$style.num"> &zwj;{{ item.value }} </div>
  18. <div v-if="item.type === 'bd'" :class="$style.num"> &zwj;{{ item.value }} </div>
  19. <div v-else-if="item.type === 'plain'" :class="$style.plain"> &zwj;{{ item.value }} </div>
  20. <div v-else-if="item.type === 'obj'" :class="$style.obj"> &zwj;{{ item.value }} </div>
  21. <!--光标-->
  22. <div v-if="item.cursor" :class="$style.cursor"></div>
  23. </div>
  24. <div
  25. v-if="formulaList.length === 0"
  26. style="color: rgb(178, 178, 178);padding-left: 45%;padding-top: 10px;"
  27. >点击此处创建公式</div
  28. >
  29. </div>
  30. <div v-show="!readOnly" class="tab mt_10 flex-lr">
  31. <div class="">
  32. <div class="" style="display:inline-block;position:relative;padding: 0 10px;">
  33. <a-button type="primary" :class="classStyle" @click="selectZb">选择指标</a-button>
  34. </div>
  35. <div class="" style="display:inline-block;position:relative;">
  36. <a-button :class="classStyle" @click="deleteItem">退格</a-button>
  37. </div>
  38. <div class="" style="display:inline-block;position:relative;padding: 0 10px;">
  39. <a-button :class="classStyle" @click="deleteItem('kh')">清空括号</a-button>
  40. </div>
  41. <div class="" style="display:inline-block;position:relative;">
  42. <a-button :class="classStyle" @click="clearAll">清空公式</a-button>
  43. </div>
  44. <div class="" style="display:inline-block;position:relative;padding: 0 10px;">
  45. <a-button :class="$style.classStylejygs" @click="checkformula">校验公式</a-button>
  46. </div>
  47. </div>
  48. </div>
  49. <a-modal v-model="ModalVisible" title="手动录入数字" @ok="ModalHandleOk">
  50. <a-form-model ref="ModalForm" :model="ModalForm">
  51. <a-form-model-item label="数字" prop="num">
  52. <a-input v-model="ModalForm.num" />
  53. </a-form-model-item>
  54. </a-form-model>
  55. </a-modal>
  56. <!-- <iam-audit-modal
  57. :single="true"
  58. :check-type="'radio'"
  59. select-type="table"
  60. :visible="visible"
  61. :treeparams="{
  62. configId: '41',
  63. }"
  64. :columns="columns"
  65. @listSelected="listSelected"
  66. @getCheckNode="getCheckNode"
  67. @handleCancel="handleCancel"
  68. ></iam-audit-modal> -->
  69. <a-modal
  70. title="选择指标"
  71. :visible="visible"
  72. :confirm-loading="confirmLoading"
  73. width="1000px"
  74. @ok="handleOk"
  75. @cancel="handleCancel"
  76. >
  77. <sd-data-table-ex
  78. ref="zblist"
  79. :data-url="zbDataUrl"
  80. :process-req="processReq"
  81. form-id="kpiIndiDef"
  82. page-id="kpi/def/definition/kpiIndiDef"
  83. :columns="zbColumns"
  84. :search-fields="['indiName']"
  85. :filter-expressions="zbExpressions"
  86. :checkType="'radio'"
  87. show-selection
  88. >
  89. </sd-data-table-ex>
  90. </a-modal>
  91. </div>
  92. </template>
  93. <script>
  94. import { message, Modal } from 'ant-design-vue'
  95. // import iamAuditModal from '@product/iam/components/iam-audit-modal.vue'
  96. import kpiService from '../kpi-service'
  97. import components from './_import-components/kpi-formula-editor-import'
  98. export default {
  99. name: 'KpiFormulaEditor',
  100. metaInfo: {
  101. title: 'KpiFormulaEditor',
  102. },
  103. components: {
  104. ...components,
  105. },
  106. props: {
  107. dataList: {
  108. type: Array,
  109. default() {
  110. return []
  111. },
  112. },
  113. defaultList: {
  114. type: Array,
  115. default() {
  116. return []
  117. },
  118. },
  119. readOnly: {
  120. type: Boolean,
  121. default: false,
  122. },
  123. zbid: {
  124. type: String,
  125. default: '',
  126. },
  127. },
  128. data() {
  129. return {
  130. confirmLoading: false,
  131. ModalForm: {
  132. num: '', // 数字
  133. },
  134. currentEntryField: '', // 当前录入的表单字段
  135. ModalVisible: false,
  136. num: [],
  137. // 公式字符串
  138. formulaStr: '',
  139. zbDataUrl: 'api/xcoa-mobile/v1/kpi-indi-def/getIndisByAttr',
  140. dataId: '',
  141. operatorId: '',
  142. formulaList: [],
  143. // 运算符
  144. operatorList: [
  145. {
  146. name: '+',
  147. id: '+',
  148. },
  149. {
  150. name: '-',
  151. id: '-',
  152. },
  153. {
  154. name: '*',
  155. id: '*',
  156. },
  157. {
  158. name: '/',
  159. id: '/',
  160. },
  161. {
  162. name: '()',
  163. id: '()',
  164. },
  165. ],
  166. classStyle: '',
  167. flag: true,
  168. visible: false,
  169. zbColumns: [
  170. {
  171. title: '序号',
  172. dataIndex: 'sortNum',
  173. customRender: (text, record, index) => `${index + 1}`,
  174. width: '80px',
  175. },
  176. {
  177. title: '指标名称',
  178. dataIndex: 'indiName',
  179. },
  180. {
  181. title: '业务分类',
  182. dataIndex: 'busiClassName',
  183. },
  184. {
  185. title: '维护单位',
  186. dataIndex: 'createDeptName',
  187. },
  188. ],
  189. zbExpressions: [],
  190. selectedRowKeys: [],
  191. selectZbkey: 0,
  192. searchValInit: '',
  193. // sdataList: [],
  194. selectList: [],
  195. }
  196. },
  197. watch: {
  198. formulaList(val) {
  199. this.$emit('change', val)
  200. if (!this.flag) {
  201. this.$emit('change', '')
  202. }
  203. },
  204. },
  205. created() {
  206. if (this.defaultList.length > 0) {
  207. this.formulaList = [...this.defaultList]
  208. }
  209. // this.sdataList = [...this.dataList]
  210. // 监听鼠标事件
  211. this.$nextTick(function() {
  212. // document.addEventListener('keydown', this.keydown, false)
  213. document.addEventListener('keypress', this.keypress, false)
  214. document.addEventListener('click', this.formulaBlur)
  215. })
  216. this.zbExpressions.push({
  217. dataType: 'str',
  218. name: 'id',
  219. op: 'ne',
  220. stringValue: `${this.zbid}`,
  221. })
  222. },
  223. destroyed() {
  224. // 移除监听事件
  225. // document.removeEventListener('keydown', this.keydown, false)
  226. document.removeEventListener('keypress', this.keypress, false)
  227. document.removeEventListener('click', this.formulaBlur)
  228. },
  229. methods: {
  230. processReq(req) {
  231. // 获取查询内容
  232. return req
  233. },
  234. handleOk() {
  235. const list = this.$refs.zblist.getSelectedRows()
  236. if (list.length === 0) {
  237. message.error('请选择指标!')
  238. } else {
  239. this.listSelected([], list)
  240. this.$refs.zblist.clearSelection()
  241. this.visible = false
  242. }
  243. },
  244. handleCancel() {
  245. this.visible = false
  246. },
  247. listSelected(keys, keyinfos) {
  248. this.visible = false
  249. if (keyinfos?.length > 0) {
  250. const zbid = '#v_' + keyinfos[0].id
  251. this.selectList = keyinfos[0]
  252. this.addItem(zbid, 'obj')
  253. }
  254. },
  255. getCheckNode(checkNode) {
  256. this.visible = false
  257. },
  258. selectZb(event) {
  259. // 阻止丢失事件
  260. event.stopPropagation()
  261. this.visible = true
  262. this.selectZbkey += 1
  263. },
  264. checkformula() {
  265. // 校验所有数字是否合规,两个plain中间的是否是数字格式
  266. let strnum = ''
  267. let info = '该公式合法'
  268. let flag = true
  269. let gs = ''
  270. this.formulaList.forEach((v) => {
  271. if (v.type === 'obj') {
  272. gs += 'o'
  273. } else {
  274. gs += v.value
  275. }
  276. })
  277. let tt = /([+\-*/]{2,})/ // +-*/运算符不能连着
  278. if (tt.test(gs)) {
  279. flag = false
  280. }
  281. tt = /\(\)/ // 不可含有空括号
  282. if (tt.test(gs)) {
  283. flag = false
  284. }
  285. tt = /^[+\-*/]/ // 运算符开头
  286. if (tt.test(gs)) {
  287. flag = false
  288. }
  289. tt = /[+\-*/]$/ // 运算符结尾
  290. if (tt.test(gs)) {
  291. flag = false
  292. }
  293. // 数字和 指标不能连着
  294. // tt = /([{0-9}{o}]{2,})/
  295. // if (tt.test(gs)) {
  296. // flag = false
  297. // }
  298. // 错误情况,(后面是运算符
  299. tt = /\([+\-*/]/
  300. if (tt.test(gs)) {
  301. flag = false
  302. }
  303. // 错误情况,)前面是运算符
  304. if (/[+\-*/]\)/.test(gs)) {
  305. flag = false
  306. }
  307. // 错误情况,(前面不是运算符
  308. // if (/[^{+}{-}{*}{/}]\(/.test(gs)) {
  309. // flag = false
  310. // }
  311. // 错误情况,使用除()+-*/之外的字符
  312. // if (/[^{+}{-}{*}{/}0-9.a-zA-Z\(\)]/.test(gs)) {
  313. // flag = false
  314. // }
  315. // 错误情况,(后面不是运算符
  316. // if (/\([+\-*/]/.test(gs)) {
  317. // flag = false
  318. // }
  319. if (flag) {
  320. // 判断数字是否标准,判断括号是否对应
  321. const stack = []
  322. const f = [...this.formulaList]
  323. this.formulaList.forEach((v, i) => {
  324. if (v.type === 'num' || v.type === 'bd') {
  325. strnum += v.value
  326. } else if (v.type === 'plain') {
  327. if (strnum !== '' && isNaN(strnum)) {
  328. flag = false
  329. info += ',' + strnum + '不是数字'
  330. } else if (v.value === '(') {
  331. stack.push('(')
  332. } else if (v.value === ')') {
  333. if (stack.length > 0) {
  334. stack.pop()
  335. } else {
  336. flag = false
  337. info += ',括号对应不上'
  338. }
  339. }
  340. strnum = ''
  341. } else if (v.type === 'obj') {
  342. if (strnum !== '') {
  343. flag = false
  344. info += ',指标前不能为数字'
  345. strnum += 'o'
  346. } else if (i !== 0 && f[i - 1].type === 'obj') {
  347. flag = false
  348. }
  349. }
  350. })
  351. if (strnum !== '' && isNaN(strnum)) {
  352. flag = false
  353. info += ',' + strnum + '不是数字'
  354. }
  355. if (stack.length !== 0) {
  356. flag = false
  357. }
  358. if (info !== '') {
  359. info = info.substring(1, info.length) + ',请修改'
  360. }
  361. if (flag) {
  362. if (f.length > 1 && f[f.length - 1].value === '-') {
  363. flag = false
  364. } else if (f.length > 1 && f[0].value === '-') {
  365. flag = false
  366. }
  367. }
  368. }
  369. if (!flag) {
  370. info = '该公式不合法'
  371. } else {
  372. if(gs.indexOf("o") === -1){
  373. info = '该公式至少选择一个指标'
  374. }else{
  375. info = '该公式合法'
  376. }
  377. }
  378. // if (!flag) {
  379. Modal.info({
  380. content: info,
  381. })
  382. return flag
  383. // }
  384. },
  385. isNumber(val) {
  386. // isNumber(val){
  387. const regPos = /^\d+(\.\d+)?$/
  388. const regNeg = /^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$/
  389. if (regPos.test(val) && regNeg.test(val)) {
  390. return true
  391. } else {
  392. return false
  393. }
  394. },
  395. openmodal() {
  396. this.ModalForm.num = ''
  397. this.currentEntryField = 'field'
  398. this.ModalVisible = true
  399. },
  400. ModalHandleOk() {
  401. this.addItem(this.ModalForm.num, 'num')
  402. this.ModalVisible = false
  403. },
  404. // 获取
  405. getFormula: function() {},
  406. // 点选时记录光标位置
  407. recordPosition(index) {
  408. // 只读模式,不可编辑
  409. if (this.readOnly) {
  410. return false
  411. }
  412. if (this.formulaList && this.formulaList.length > 0) {
  413. this.formulaList = this.formulaList.map((item, itemIndex) => {
  414. item.cursor = false
  415. if (index > -1 && index === itemIndex) {
  416. item.cursor = true
  417. } else if (index !== 0 && !index && itemIndex === this.formulaList.length - 1) {
  418. item.cursor = true
  419. }
  420. return item
  421. })
  422. } else {
  423. this.formulaList = [
  424. {
  425. cursor: true,
  426. type: 'placeholder',
  427. value: '',
  428. },
  429. ]
  430. }
  431. this.$forceUpdate()
  432. },
  433. // 失去焦点
  434. formulaBlur(e) {
  435. if (!this.visible) {
  436. const v = this.formulaList.findIndex((i) => i.value === '')
  437. if (this.formulaList.length === 1 && v > -1) {
  438. this.formulaList = []
  439. } else if (this.formulaList.length > 0 && this.formulaList[0].value !== '') {
  440. this.formulaList.splice(0, 0, {
  441. cursor: false,
  442. type: 'placeholder',
  443. value: '',
  444. })
  445. }
  446. this.formulaList = this.formulaList?.map((item) => {
  447. item.cursor = false
  448. return item
  449. })
  450. }
  451. },
  452. /**
  453. * @returns {addItem<*, void, *>}
  454. * 添加字段
  455. * type obj 字段 num 数字 plain符号
  456. * place 是否修改光标位置
  457. */
  458. addItem: function(val, type, place = true) {
  459. if (!val) return false
  460. const that = this
  461. // 插入括号
  462. if (type === 'plain' && val === '()') {
  463. val = '('
  464. setTimeout(function() {
  465. that.addItem(')', type, false)
  466. }, 50)
  467. }
  468. const obj = {}
  469. const data = {
  470. value: '',
  471. key: val,
  472. type: type,
  473. }
  474. if (type === 'obj') {
  475. // 获取数据 为 value 赋值
  476. // const obj = this.selectList?.find((item) => '#v_' + item.id === val)
  477. const obj = this.selectList
  478. data.value = obj.indiName
  479. } else {
  480. data.value = val
  481. }
  482. if (this.formulaList && this.formulaList.length > 0) {
  483. const length = this.formulaList.length
  484. for (let i = 0; i < length; i++) {
  485. // 查找光标位置 如果光标位置为空 则在最后添加
  486. if (this.formulaList[i].cursor) {
  487. this.formulaList.splice(i + 1, 0, data)
  488. // place && this.recordPosition(i + 1)
  489. if (place) this.recordPosition(i + 1)
  490. break
  491. } else if (i === this.formulaList.length - 1) {
  492. this.formulaList.push(data)
  493. this.recordPosition(this.formulaList.length - 1)
  494. }
  495. }
  496. } else {
  497. if (!this.formulaList) {
  498. this.formulaList = []
  499. }
  500. this.formulaList.push(data)
  501. this.recordPosition(this.formulaList.length - 1)
  502. }
  503. },
  504. // 清除全部
  505. clearAll() {
  506. this.formulaList = []
  507. const that = this
  508. setTimeout(function() {
  509. that.recordPosition()
  510. }, 100)
  511. },
  512. // 删除
  513. deleteItem(type) {
  514. const arr = JSON.parse(JSON.stringify(this.formulaList))
  515. var index = null
  516. const length = arr?.length
  517. var gbi = 0
  518. if (type === 'kh') {
  519. for (let i = length - 1; i > 0; i--) {
  520. if (arr[i].key && (arr[i].value === '(' || arr[i].value === ')')) {
  521. index = i
  522. this.formulaList.splice(index, 1)
  523. }
  524. }
  525. const that = this
  526. setTimeout(function() {
  527. that.recordPosition()
  528. }, 100)
  529. } else {
  530. for (let i = 0; i < length; i++) {
  531. if (arr[i].cursor && arr[i].key) {
  532. index = i
  533. if (type === 'del') {
  534. index = i + 1
  535. gbi = index
  536. break
  537. }
  538. if (index > -1) {
  539. this.formulaList.splice(index, 1)
  540. if (type === 'del') {
  541. } else {
  542. gbi = index - 1
  543. break
  544. }
  545. }
  546. }
  547. }
  548. const that = this
  549. setTimeout(function() {
  550. that.recordPosition(gbi)
  551. }, 100)
  552. }
  553. },
  554. // 键盘输入
  555. keydown(e) {
  556. // 禁止输入
  557. // 检测光标是否存在
  558. var index = null
  559. const cursorData = this.formulaList?.find((item, itemIndex) => {
  560. if (item.cursor) {
  561. index = itemIndex
  562. }
  563. return item.cursor
  564. })
  565. if (!cursorData) {
  566. return false
  567. }
  568. // 左右移动键控制光标位置
  569. if (e && [37, 39].includes(e.keyCode)) {
  570. if (e.keyCode === 37) {
  571. index = index - 1
  572. } else {
  573. index = index + 1
  574. }
  575. if (index > -1 && index < this.formulaList.length) {
  576. this.recordPosition(index)
  577. }
  578. } else if (e && e.keyCode === 8) {
  579. // Backspace 键 删除前面的值
  580. this.deleteItem()
  581. } else if (e && [107, 109, 106, 111].includes(e.keyCode)) {
  582. // 运算符列表
  583. this.addItem(e.key, 'plain')
  584. } else if (e && [190].includes(e.keyCode)) {
  585. this.addItem(e.key, 'plain')
  586. } else if (e && e.shiftKey && [16, 49, 57].includes(e.keyCode)) {
  587. if (e.keyCode === 49) e.key = ')'
  588. } else if (e && e.shiftKey && [48, 57].includes(e.keyCode)) {
  589. // 括号
  590. if (e.keyCode === 48) e.key = ')'
  591. if (e.keyCode === 57) e.key = '('
  592. this.addItem(e.key, 'plain')
  593. } else if (e && e.keyCode === 46) {
  594. // delete键删除光标后面的值
  595. this.deleteItem('del')
  596. } else {
  597. document.returnValue = false
  598. var tt = /^([1-9]{1}[0-9]{0,7})$/ // 能输入正数
  599. if (tt.test(e.key)) {
  600. // 输入为数字 插入数字
  601. // this.addItem(e.key, 'num')
  602. this.addItem(String.fromCharCode(e.key), 'num')
  603. } else {
  604. this.addItem(String.fromCharCode(e.key), 'plain')
  605. }
  606. }
  607. },
  608. keypress(e) {
  609. // 禁止输入
  610. // 检测光标是否存在
  611. var index = null
  612. const cursorData = this.formulaList?.find((item, itemIndex) => {
  613. if (item.cursor) {
  614. index = itemIndex
  615. }
  616. return item.cursor
  617. })
  618. if (!cursorData) {
  619. return false
  620. }
  621. var key = e.keyCode
  622. // 左右移动键控制光标位置
  623. if (e && [37, 39].includes(e.keyCode)) {
  624. if (e.keyCode === 37) {
  625. index = index - 1
  626. } else {
  627. index = index + 1
  628. }
  629. if (index > -1 && index < this.formulaList.length) {
  630. this.recordPosition(index)
  631. }
  632. } else if (e && e.keyCode === 8) {
  633. // Backspace 键 删除前面的值
  634. this.deleteItem()
  635. // } else if (e && [107, 109, 106, 111].includes(e.keyCode)) {
  636. // 运算符列表
  637. // this.addItem(e.key, 'plain')
  638. } else if (e && [190].includes(e.keyCode)) {
  639. this.addItem(e.key, 'plain')
  640. } else if (e && e.shiftKey && [16, 49, 57].includes(e.keyCode)) {
  641. if (e.keyCode === 49) e.key = ')'
  642. } else if (e && e.shiftKey && [48, 57].includes(e.keyCode)) {
  643. // 括号
  644. if (e.keyCode === 48) e.key = ')'
  645. if (e.keyCode === 57) e.key = '('
  646. this.addItem(e.key, 'plain')
  647. // } else if (e && e.keyCode === 46) {
  648. // delete键删除光标后面的值
  649. // this.deleteItem('del')
  650. } else {
  651. document.returnValue = false
  652. var tt = /^([0-9]{1}[0-9]{0,7})$/ // 能输入正数
  653. // var tt = /^\\d+(\\.{0,1}\\d+){0,1}$/
  654. if (tt.test(e.key)) {
  655. // 输入为数字 插入数字
  656. // this.addItem(e.key, 'num')
  657. if (tt.test(String.fromCharCode(key))) {
  658. this.addItem(String.fromCharCode(key), 'num')
  659. } else if (['+', '-', '*', '/', '.'].includes(String.fromCharCode(key))) {
  660. this.addItem(String.fromCharCode(key), 'plain')
  661. }
  662. } else {
  663. if (
  664. String.fromCharCode(key) === '+' ||
  665. String.fromCharCode(key) === '-' ||
  666. String.fromCharCode(key) === '*' ||
  667. String.fromCharCode(key) === '/' ||
  668. String.fromCharCode(key) === '(' ||
  669. String.fromCharCode(key) === ')'
  670. ) {
  671. this.addItem(String.fromCharCode(key), 'plain')
  672. } else if (String.fromCharCode(key) === '.') {
  673. this.addItem(String.fromCharCode(key), 'bd')
  674. }
  675. }
  676. }
  677. },
  678. /**
  679. * 公式转为字符串
  680. * 格式 [id]符号数字
  681. * **/
  682. parsingFormula: function(formulaStr) {
  683. let str = ''
  684. let arr = []
  685. arr = this.formulaList?.map((item) => {
  686. let val = item.key
  687. if (val) {
  688. if (item.type === 'obj') {
  689. val = '[' + val + ']'
  690. }
  691. str = str + val
  692. }
  693. return val
  694. })
  695. return str
  696. },
  697. },
  698. }
  699. </script>
  700. <style module lang="scss">
  701. @use '@/common/design' as *;
  702. #formulaPage {
  703. .formulaView {
  704. padding: 10px 11px;
  705. width: 100%;
  706. height: 58px;
  707. border: 1px solid #d9d9d9;
  708. line-height: 1.3;
  709. font-size: 16px;
  710. overflow-y: scroll;
  711. color: rgba(0, 0, 0, 0.65);
  712. border-radius: 4px;
  713. .contentItem {
  714. position: relative;
  715. height: 16px;
  716. cursor: text;
  717. user-select: none;
  718. display: flex;
  719. align-items: center;
  720. float: left;
  721. .cursor {
  722. height: 16px;
  723. width: 1px;
  724. background: #333;
  725. animation: defaultCursor 1s steps(2) infinite;
  726. position: absolute;
  727. right: 0;
  728. }
  729. .obj {
  730. padding: 0 5px;
  731. margin: 0 1px;
  732. background: #f1f1f1;
  733. border-radius: 3px;
  734. }
  735. .num {
  736. // color: #000;
  737. background: #fff;
  738. padding: 0 1px 0 0;
  739. }
  740. .plain {
  741. margin: 0px 4px;
  742. }
  743. .placeholder {
  744. width: 4px;
  745. }
  746. }
  747. }
  748. .classStylejygs {
  749. border-color: #40a9ff;
  750. }
  751. }
  752. @keyframes defaultCursor {
  753. 0% {
  754. opacity: 1;
  755. }
  756. 100% {
  757. opacity: 0;
  758. }
  759. }
  760. .search {
  761. // width: 219px;
  762. margin-bottom: 10px;
  763. width: 50%;
  764. }
  765. </style>