cui-calculator.vue 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. <template>
  2. <uni-popup ref="popup">
  3. <div style="width: 700rpx;">
  4. <view :class="['cui-calculator','flex-cncc',size]">
  5. <view class="cui-calculator-title" @click="tapCopy">
  6. <text>{{toThousands(curNumber)}}</text>
  7. </view>
  8. <view class="cui-content">
  9. <uni-row v-for="(row,index) in buttons" :key="index" class="row">
  10. <uni-col v-for="(item,subIndex) in row" :key="subIndex"
  11. :span="item.span?item.span:(24/row.length)">
  12. <div class="col">
  13. <view class="cui-cell flex-cncc"
  14. :class="[(waitInputNumberTwo&&item.name==symbol)?'active':'',item.width == 2?'big':'',item.border?'border':'',item.type]"
  15. @click.stop="tapItem(item)" @touchstart="touchStart">
  16. <!-- <uni-icons v-if="item.type=='backspace'" custom-prefix="iconfont"
  17. type="icon-backspace" color="#FF8000" size="26px"></uni-icons> -->
  18. <span v-if="item.type=='backspace'">←</span>
  19. <span v-else>{{item.name}}</span>
  20. </view>
  21. </div>
  22. </uni-col>
  23. </uni-row>
  24. </view>
  25. </view>
  26. </div>
  27. </uni-popup>
  28. </template>
  29. <script>
  30. import Decimal from "decimal.js";
  31. const toThousands = (num = 0) => {
  32. return num.toString().replace(/\d+/, function(n) {
  33. return n.replace(/(\d)(?=(?:\d{3})+$)/g, '$1,');
  34. });
  35. };
  36. function isValidNumber(str) {
  37. return Math.abs(parseFloat(str)) > 0 || str == "0";
  38. }
  39. export default {
  40. props: {
  41. size: {
  42. type: String,
  43. default: "normal" // small,normal
  44. }
  45. },
  46. data() {
  47. return {
  48. toThousands,
  49. curNumber: '0', //计算器显示区域值
  50. buttons: [
  51. [{ //计算器各按键
  52. name: 'C',
  53. type: 'clear',
  54. border: true
  55. }, {
  56. name: 'backspace',
  57. type: 'backspace',
  58. border: true
  59. }, {
  60. name: '%',
  61. type: 'percent',
  62. border: false
  63. }, {
  64. name: '/',
  65. type: 'operator',
  66. border: false
  67. }],
  68. [{
  69. name: '7',
  70. type: 'number',
  71. border: true
  72. }, {
  73. name: '8',
  74. type: 'number',
  75. border: false
  76. }, {
  77. name: '9',
  78. type: 'number',
  79. border: false
  80. }, {
  81. name: '*',
  82. type: 'operator',
  83. border: false
  84. }],
  85. [{
  86. name: '4',
  87. type: 'number',
  88. border: true
  89. }, {
  90. name: '5',
  91. type: 'number',
  92. border: false
  93. }, {
  94. name: '6',
  95. type: 'number',
  96. border: false
  97. }, {
  98. name: '+',
  99. type: 'operator',
  100. border: false
  101. }],
  102. [{
  103. name: '1',
  104. type: 'number',
  105. border: true
  106. }, {
  107. name: '2',
  108. type: 'number',
  109. border: false
  110. }, {
  111. name: '3',
  112. type: 'number',
  113. border: false
  114. }, {
  115. name: '-',
  116. type: 'operator',
  117. border: false
  118. }],
  119. [{
  120. name: '0',
  121. type: 'number',
  122. border: true,
  123. span: 12
  124. }, {
  125. name: '.',
  126. type: 'point',
  127. border: false,
  128. span: 6
  129. }, {
  130. name: '=',
  131. type: 'equal',
  132. border: false,
  133. span: 6
  134. }]
  135. ],
  136. numberOne: '', //变量一
  137. symbol: '', //运算符
  138. complete: false, //判断是否完成一次计算
  139. waitInputNumberTwo: false,
  140. formula: []
  141. }
  142. },
  143. methods: {
  144. open() {
  145. this.$refs["popup"].open();
  146. },
  147. setCurNumber(value) {
  148. this.curNumber = value;
  149. },
  150. getCurNumber() {
  151. return this.curNumber;
  152. },
  153. touchStart() {
  154. uni.vibrateShort();
  155. },
  156. /**
  157. * 1. 无输入
  158. * 2. 计算已完成
  159. * 3. 1
  160. * 4. 1.2
  161. * 6. 1+
  162. * 7. 1+.
  163. * 8. 1+2.3
  164. */
  165. //计算器方法二:
  166. tapItem: function(item) {
  167. // console.log("!!", item)
  168. switch (item.type) {
  169. case 'point': //小数点
  170. if (this.complete || this.waitInputNumberTwo) {
  171. this.curNumber = '0';
  172. this.complete = false;
  173. }
  174. if (!this.curNumber.includes('.')) {
  175. this.curNumber = this.curNumber + '.';
  176. }
  177. break;
  178. case 'number': //数字
  179. if (this.complete || this.waitInputNumberTwo) {
  180. this.complete = false;
  181. this.curNumber = item.name;
  182. // this.formula = [];
  183. } else if ((this.curNumber + "").includes('.')) {
  184. this.curNumber += item.name;
  185. } else {
  186. this.curNumber = parseInt(this.curNumber + item.name) + "";
  187. }
  188. break;
  189. case 'percent':
  190. if (isValidNumber(this.curNumber)) {
  191. this.curNumber = Decimal.div(parseFloat(this.curNumber), 100);
  192. } else if (this.numberOne) {
  193. //取上一个数
  194. this.curNumber = Decimal.div(parseFloat(this.numberOne), 100);
  195. }
  196. break;
  197. case 'sign':
  198. if (isValidNumber(this.curNumber)) {
  199. this.curNumber = "" + (0 - parseFloat(this.curNumber));
  200. } else if (this.numberOne) {
  201. //取上一个数
  202. this.curNumber = "" + (0 - parseFloat(this.numberOne));
  203. }
  204. break;
  205. case 'backspace':
  206. let temp = "" + this.curNumber;
  207. if (/e\+\d$/.test(temp)) {
  208. temp = temp.substring(0, temp.length - 3);
  209. } else {
  210. temp = temp.substring(0, temp.length - 1);
  211. }
  212. if (temp == "" || temp == '-') {
  213. this.curNumber = '0';
  214. } else {
  215. this.curNumber = temp;
  216. }
  217. break;
  218. case 'operator': //运算符
  219. // 加减乘除
  220. this.complete = false;
  221. if (this.waitInputNumberTwo) {
  222. this.symbol = item.name;
  223. } else {
  224. if (this.numberOne && this.symbol && isValidNumber(this.curNumber)) {
  225. this.curNumber = this.calc(this.symbol, this.numberOne, this.curNumber);
  226. this.numberOne = this.curNumber;
  227. this.symbol = item.name;
  228. this.waitInputNumberTwo = true;
  229. } else if (!this.numberOne && !this.symbol && isValidNumber(this.curNumber)) {
  230. this.numberOne = this.curNumber;
  231. this.symbol = item.name;
  232. this.waitInputNumberTwo = true;
  233. }
  234. }
  235. break;
  236. case 'equal': //等号
  237. if (!this.complete) {
  238. // console.log("!!!!!!!!!!!!", this.symbol, this.numberOne, this.curNumber)
  239. if (this.numberOne) {
  240. this.curNumber = this.calc(this.symbol, this.numberOne, this.curNumber);
  241. } else {
  242. this.curNumber = parseFloat(this.curNumber);
  243. }
  244. this.complete = true;
  245. this.numberOne = '';
  246. this.symbol = '';
  247. }
  248. // this.addToFormula(item);
  249. break;
  250. case 'clear': //清除符
  251. this.clear();
  252. break;
  253. }
  254. if (item.type != "operator") {
  255. this.waitInputNumberTwo = false;
  256. }
  257. },
  258. // addToFormula(item) {
  259. // if ("1234567890.".includes(item.name)) {
  260. // if (this.formula.length) {
  261. // this.formula[this.formula.length - 1] += item.name;
  262. // } else {
  263. // this.formula.push(item.name);
  264. // }
  265. // } else {
  266. // this.formula.push(item.name);
  267. // }
  268. // },
  269. // formulaLastIsSymbol() {
  270. // return "-+*/".includes(this.formula[this.formula.length - 1]);
  271. // },
  272. /**
  273. * 清除
  274. * */
  275. clear: function() {
  276. this.curNumber = '0';
  277. this.numberOne = '';
  278. this.symbol = '';
  279. this.compile = false;
  280. this.formula = [];
  281. },
  282. /**
  283. * 除法
  284. * */
  285. calc: function(symbol, arg1, arg2) {
  286. if (symbol == '-') {
  287. return Decimal.sub(arg1, arg2);
  288. } else if (symbol == '+') {
  289. return Decimal.add(arg1, arg2);
  290. } else if (symbol == '*') {
  291. return Decimal.mul(arg1, arg2);
  292. } else if (symbol == '/') {
  293. return Decimal.div(arg1, arg2);
  294. }
  295. },
  296. tapCopy() {
  297. uni.setClipboardData({
  298. data: "" + this.curNumber,
  299. success: () => {
  300. uni.showToast({
  301. title: "复制成功"
  302. })
  303. }
  304. })
  305. }
  306. }
  307. }
  308. </script>
  309. <style lang="less">
  310. .cui-calculator {
  311. background-color: #333333;
  312. box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04);
  313. width: 100%;
  314. }
  315. .cui-calculator-title,
  316. .cui-calculator-formula {
  317. width: 100%;
  318. height: 120rpx;
  319. line-height: 120rpx;
  320. padding: 0 24rpx;
  321. text-align: right;
  322. background-color: #333333;
  323. font-size: 50rpx;
  324. font-weight: 600;
  325. color: #FFFFFF;
  326. box-sizing: border-box;
  327. overflow: auto;
  328. }
  329. .cui-content {
  330. width: 100%;
  331. background-color: #FFFFFF;
  332. // display: flex;
  333. // flex-direction: row;
  334. // justify-content: flex-start;
  335. // align-items: flex-start;
  336. // flex-wrap: wrap;
  337. box-sizing: border-box;
  338. border: 1px #f5f5f5 solid;
  339. .row {
  340. width: 100%;
  341. background-color: #A5A4A4;
  342. }
  343. .col {
  344. height: 98rpx;
  345. line-height: 98rpx;
  346. padding: 6rpx;
  347. box-sizing: border-box;
  348. }
  349. .cui-cell {
  350. width: 100%;
  351. height: 100%;
  352. text-align: center;
  353. font-size: 44rpx;
  354. font-weight: 600;
  355. color: black;
  356. border-bottom: 1px solid #f5f5f5;
  357. border-left: 1px solid #f5f5f5;
  358. background-color: white;
  359. box-sizing: border-box;
  360. text-align: center;
  361. background-color: #fafafa;
  362. border-radius: 20rpx;
  363. &:active {
  364. filter: brightness(0.95);
  365. transform: scale(0.95);
  366. }
  367. }
  368. .cui-cell.border {
  369. border-left: none;
  370. }
  371. .cui-cell.active {
  372. background-color: #ccc;
  373. }
  374. .cui-cell {
  375. &.operator,
  376. &.percent,
  377. &.backspace {
  378. color: #FF7433
  379. }
  380. &.sign {
  381. color: #FF7433
  382. }
  383. &.equal {
  384. color: white;
  385. background-color: #FF7433
  386. }
  387. &.clear {
  388. color: #F75000;
  389. }
  390. }
  391. }
  392. .small {
  393. .cui-calculator-title {
  394. height: 60rpx;
  395. line-height: 60rpx;
  396. font-size: 25rpx;
  397. }
  398. .cui-calculator-formula {
  399. height: 40rpx;
  400. line-height: 40px;
  401. font-size: 22rpx;
  402. }
  403. .col {
  404. height: 45rpx;
  405. line-height: 45rpx;
  406. padding: 6rpx;
  407. }
  408. .cui-cell {
  409. font-size: 22rpx;
  410. border-radius: 12rpx;
  411. }
  412. }
  413. </style>