迭代textarea

szh-new
lijingjia 4 months ago
parent 19191cc029
commit fb7028df22

@ -67,7 +67,7 @@
</template>
<script lang="ts" setup name="DsFileList">
import { ref, defineExpose, reactive, defineProps, unref } from 'vue'
import { ref, defineExpose, reactive, defineProps, watch } from 'vue'
import { GetOpFileList, BatchDelFiles, DownloadOpFile } from './api'
//
import { useMessage } from '/@/hooks/web/useMessage'
@ -138,6 +138,12 @@
return false
}
}
watch(
() => props.id,
() => {
init()
}
)
init()
defineExpose({
init

@ -1,3 +1,8 @@
/*
* @Desc:
* @Author: lijj
* @Date: 2024-07-17 08:39:50
*/
import type { Component } from 'vue'
import type { ComponentType } from './types/index'
@ -24,6 +29,7 @@ import {
import ApiRadioGroup from './components/ApiRadioGroup.vue'
import RadioButtonGroup from './components/RadioButtonGroup.vue'
import ApiSelect from './components/ApiSelect.vue'
import InputTextArea from './components/InputTextArea.vue'
import ApiTree from './components/ApiTree.vue'
import ApiTreeSelect from './components/ApiTreeSelect.vue'
import ApiCascader from './components/ApiCascader.vue'
@ -41,7 +47,7 @@ componentMap.set('Input', Input)
componentMap.set('InputGroup', Input.Group)
componentMap.set('InputPassword', Input.Password)
componentMap.set('InputSearch', Input.Search)
componentMap.set('InputTextArea', Input.TextArea)
componentMap.set('InputTextArea', InputTextArea)
componentMap.set('InputNumber', InputNumber)
componentMap.set('AutoComplete', AutoComplete)

@ -284,6 +284,7 @@
...propsData,
...on,
...bindValue,
...props.schema
}
if (!renderComponentContent) {

@ -0,0 +1,178 @@
<!--
* @Desc: 东胜文本框
* @Author: lijj
* @Date: 2024-08-05 16:16:08
-->
<template>
<div class="ds-textarea">
<div class="ds-textarea-opt">
<span title="放大(big)" class="iconfont icon-ic_search24px" @click="toBig"></span>
<span v-for="item in cutList" :key="item" class="ds-cut-btn" @click="changeCode(item)">{{ item }}</span>
</div>
<a-textarea
v-bind="$attrs"
:disabled="props.disabled"
v-model:value="state"
@blur="textareaBlur"
/>
<a-modal
class="ds-modal-small"
:title="props.label"
width="70%"
v-model:visible="contentFlag"
>
<a-form
layout="vertical"
>
<a-form-item>
<a-textarea v-model:value="state" :disabled="props.disabled" style="min-height: 50vh;"></a-textarea>
</a-form-item>
</a-form>
<template #footer></template>
</a-modal>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, unref, watch } from 'vue'
import { useRuleFormItem } from '/@/hooks/component/useFormItem'
import { useAttrs } from '/@/hooks/core/useAttrs'
import { useI18n } from '/@/hooks/web/useI18n'
export default defineComponent({
name: 'InputTextArea',
inheritAttrs: false,
props: {
value: [Array, Object, String, Number],
disabled: {
type: Boolean
},
label: { type: String }
},
emits: ['change', 'update:value'],
setup(props, { emit }) {
const attrs = useAttrs()
const { t } = useI18n()
const [state] = useRuleFormItem(props, 'value', 'change')
//
const cutList = attrs.value.slice || []
function emitChange() {
}
//
const contentFlag = ref(false)
const toBig = () => {
contentFlag.value = true
}
// function handleChange(_, ...args) {
// emit('change', _, ...args)
// emitData.value = args
// }
//
const changeCode = (len) => {
const value = state.value
var textArr: any = value.match(/.+[\n]*/g)
var subValue = ''
for (var j = 0; j < textArr.length; j++) {
var subArr = textArr[j].match(/[\w]+[ ]*[\n]*|[\d]+[ ]*[\n]*|[^\w\d]+[ ]*[\n]*/g)
var count = 0
for (var i = 0; i < subArr.length; i++) {
count += subArr[i].replace(/\n/g, '').length
while (count > len) {
subValue += '\n'
count = subArr[i].replace(/\n/g, '').length
if (count > len) {
subValue += subArr[i].substring(0, len)
subValue += '\n'
subArr[i] = subArr[i].substring(len)
count = subArr[i].replace(/\n/g, '').length
}
}
subValue += subArr[i]
}
if (j + 1 < textArr.length) {
subValue += '\n'
}
}
subValue = subValue.replace(/[\n]+/g, '\n')
subValue = subValue.replace(/[ ]+[\n]+/g, '\n')
subValue = subValue.replace(/[ ]+$/g, '')
subValue = subValue.replace(/^\s+/, '')
state.value = subValue
}
function ToCDB(str) {
var tmp = ''
for (var i = 0; i < str.length; i++) {
if (str.charCodeAt(i) > 65248 && str.charCodeAt(i) < 65375) {
tmp += String.fromCharCode(str.charCodeAt(i) - 65248)
} else {
tmp += String.fromCharCode(str.charCodeAt(i))
}
}
tmp = tmp.replace(//gi, ',')
tmp = tmp.replace(/。/gi, '.')
tmp = tmp.replace(//gi, ';')
tmp = tmp.replace(//gi, ':')
tmp = tmp.replace(//gi, '?')
tmp = tmp.replace(//gi, '!')
tmp = tmp.replace(/《/gi, '<<')
tmp = tmp.replace(/》/gi, '>>')
tmp = tmp.replace(//gi, "'")
tmp = tmp.replace(//gi, "'")
tmp = tmp.replace(/、/gi, ',')
// tab
tmp = tmp.replace(/\t/gi, ' ')
return tmp
}
//
const textareaBlur = () => {
if (cutList.length == 0) return
state.value = ToCDB(state.value).toUpperCase()
}
watch(
() => state.value,
(v) => {
emit('update:value', v)
}
)
return { attrs, t, props, state, toBig, contentFlag, cutList, changeCode, textareaBlur }
},
})
</script>
<style lang="less" scoped>
.ds-textarea {
position: relative;
&-opt {
position: absolute;
right: 0;
top: -22px;
.iconfont {
display: inline-block;
height: 16px;
width: 16px;
border-radius: 2px;
font-size: 10px;
text-align: center;
background: #F5F9FC;
color: @primary-color;
margin-right: 0;
margin-left: 4px;
margin-bottom: 4px;
cursor: pointer;
}
.ds-cut-btn {
display: inline-block;
width: 32px;
height: 16px;
line-height: 16px;
margin-left: 4px;
margin-bottom: 4px;
background: #F5F9FC;
color: @primary-color;
font-size: 10px;
text-align: center;
border-radius: 2px;
cursor: pointer;
}
}
}
</style>

@ -106,7 +106,7 @@
&-light {
background-color: #fff;
padding-bottom: 20px;
.@{menu-prefix-cls}-submenu-active {
color: @primary-color !important;
@ -117,6 +117,7 @@
}
&-dark {
padding-bottom: 20px;
.@{menu-prefix-cls}-submenu-active {
color: #fff !important;
}

@ -43,6 +43,8 @@
<FullScreen v-if="getShowFullScreen" :class="`${prefixCls}-action__item fullscreen-item`" /> -->
<TabRedo v-if="getShowRedo" />
<!-- 原退出登录设置项目 -->
<SettingDrawer v-if="getShowSetting" :class="`${prefixCls}-action__item`" />
<AppLocalePicker
v-if="getShowLocalePicker"
:reload="true"
@ -51,8 +53,6 @@
/>
<UserDropDown :theme="getHeaderTheme" />
<!-- 原退出登录设置项目 -->
<SettingDrawer v-if="getShowSetting" :class="`${prefixCls}-action__item`" />
</div>
</Header>
</template>

@ -188,12 +188,12 @@ export default defineComponent({
def={unref(getCanDrag)}
disabled={!unref(getShowMenuRef)}
/>
<SwitchItem
{/* <SwitchItem
title={t('layout.setting.menuSearch')}
event={HandlerEnum.HEADER_SEARCH}
def={unref(getShowSearch)}
disabled={!unref(getShowHeader)}
/>
/> */}
<SwitchItem
title={t('layout.setting.menuAccordion')}
event={HandlerEnum.MENU_ACCORDION}
@ -239,20 +239,7 @@ export default defineComponent({
unref(getIsMixSidebar)
}
/>
<SelectItem
title={t('layout.setting.menuCollapseButton')}
event={HandlerEnum.MENU_TRIGGER}
def={triggerDef}
options={triggerOptions}
disabled={!unref(getShowMenuRef) || unref(getIsMixSidebar)}
/>
<SelectItem
title={t('layout.setting.contentMode')}
event={HandlerEnum.CONTENT_MODE}
def={unref(getContentMode)}
options={contentModeOptions}
/>
<InputNumberItem
{/* <InputNumberItem
title={t('layout.setting.expandedMenuWidth')}
max={600}
min={100}
@ -261,7 +248,7 @@ export default defineComponent({
disabled={!unref(getShowMenuRef)}
defaultValue={unref(getMenuWidth)}
formatter={(value: string) => `${parseInt(value)}px`}
/>
/> */}
</>
)
}
@ -316,11 +303,11 @@ export default defineComponent({
disabled={unref(getIsHorizontal)}
/>
<SwitchItem
{/* <SwitchItem
title={t('layout.setting.header')}
event={HandlerEnum.HEADER_SHOW}
def={unref(getShowHeader)}
/>
/> */}
<SwitchItem
title="Logo"
event={HandlerEnum.SHOW_LOGO}
@ -393,8 +380,6 @@ export default defineComponent({
>
{unref(getShowDarkModeToggle) && <Divider>{() => t('layout.setting.darkMode')}</Divider>}
{unref(getShowDarkModeToggle) && <AppDarkModeToggle class="mx-auto" />}
<Divider>{() => t('layout.setting.navMode')}</Divider>
{renderSidebar()}
<Divider>{() => t('layout.setting.sysTheme')}</Divider>
{renderMainTheme()}
<Divider>{() => t('layout.setting.headerTheme')}</Divider>

@ -1,3 +1,8 @@
<!--
* @Desc:
* @Author: lijj
* @Date: 2024-07-17 08:39:50
-->
<template>
<div>
<!-- <div style="margin-right: 20px" @click="handleLoginOut()">
@ -5,7 +10,7 @@
<span>退出登录</span>
</div> -->
<div @click="openDrawer(true)">
<Icon icon="ion:settings-outline" />
<Icon icon="ion:settings-outline" style="position: relative; top: -2px;"/>
<SettingDrawer @register="register" />
</div>
</div>

@ -1,6 +1,6 @@
<template>
<span :class="`${prefixCls}__extra-redo`" @click="handleRedo">
<RedoOutlined :spin="loading" />
<RedoOutlined style="font-size: 12px; position: relative; top: -2px;" :spin="loading" />
</span>
</template>
<script lang="ts">

@ -20,7 +20,7 @@ html[data-theme='light'] {
z-index: 10;
height: @multiple-height + 2;
line-height: @multiple-height + 2;
background-color: @component-background;
background-color: transparent;
// border-bottom: 1px solid @border-color-base;
.ant-tabs-small {
height: @multiple-height;
@ -46,7 +46,7 @@ html[data-theme='light'] {
padding-top: 2px;
height: @multiple-height;
margin: 0;
background-color: @component-background;
background-color: transparent;
border: 0;
box-shadow: none;

@ -200,6 +200,12 @@ export default {
// 商品
GetClientGoodsList: () => {
return GetClientGoodsList().then((res) => {
console.log(res.data)
if (res?.data.length) {
res.data.forEach((item) => {
item['pinYinCode'] = `${item.goodName}(${item.goodsCode})`
})
}
return res.data
})
},

@ -92,6 +92,11 @@ export const formSchema: FormSchema[] = [
field: 'note',
label: '备注',
component: 'InputTextArea',
colProps: { span: 24 }
colProps: { span: 24 },
componentProps: {
autoSize: {
minRows: 5
}
}
}
]

@ -1,113 +0,0 @@
<template>
<textarea
class="ant-input"
v-model="value"
:style="`width:100%;display:inline-block;height: ${height}px`"
@input="debounce(textareaChange, 300, $event)"
@blur="textareaBlur"
></textarea>
<!-- -->
</template>
<script>
let timer
export default {
name: '',
props: {
parentVal: {
type: String,
default: ''
},
type: {
type: String,
default: ''
},
height: {
type: Number,
default: 120
},
openToCDB: {
type: Boolean,
default: false
}
},
data() {
return {
value: this.parentVal || '',
inEdit: false
}
},
watch: {
parentVal(nval, oval) {
if (this.inEdit) {
return false
}
this.value = nval
}
},
mounted() {},
methods: {
debounce(func, wait, ...args) {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
func.apply(this, args)
}, wait)
},
textareaBlur() {
if (this.openToCDB) {
this.value = this.ToCDB(this.value).toUpperCase()
this.$emit('getTextareaChange', {
type: this.type,
value: this.value
})
}
},
textareaChange(e) {
this.inEdit = true
setTimeout(() => {
this.inEdit = false
}, 800)
this.$emit('getTextareaChange', {
type: this.type,
value: this.value
})
},
ToCDB(str) {
var tmp = ''
for (var i = 0; i < str.length; i++) {
if (str.charCodeAt(i) > 65248 && str.charCodeAt(i) < 65375) {
tmp += String.fromCharCode(str.charCodeAt(i) - 65248)
} else {
tmp += String.fromCharCode(str.charCodeAt(i))
}
}
tmp = tmp.replace(//gi, ',')
tmp = tmp.replace(/。/gi, '.')
tmp = tmp.replace(//gi, ';')
tmp = tmp.replace(//gi, ':')
tmp = tmp.replace(//gi, '?')
tmp = tmp.replace(//gi, '!')
tmp = tmp.replace(/《/gi, '<<')
tmp = tmp.replace(/》/gi, '>>')
tmp = tmp.replace(//gi, "'")
tmp = tmp.replace(//gi, "'")
tmp = tmp.replace(/、/gi, ',')
// tab
tmp = tmp.replace(/\t/gi, ' ')
//
if (/[\u4E00-\u9FA5]+/g.test(tmp) && ['description', 'marks'].includes(this.type)) {
tmp = tmp.replace(/[\u4E00-\u9FA5]+/g, '')
this.$message.error(`${this.getTypeName(this.type)}中,不支持中文字符`)
}
return tmp
},
getTypeName(type) {
switch (type) {
case 'marks':
return '封志号 / 标记与号码'
case 'description':
return '包装种类与货名'
}
}
}
}
</script>

@ -1992,7 +1992,7 @@ export const cargoInfoFormSchema1: FormSchema[] = [
span: 12,
},
componentProps: {
minRow: 7,
slice: [14, 15]
},
},
{
@ -2003,7 +2003,7 @@ export const cargoInfoFormSchema1: FormSchema[] = [
dynamicDisabled: false,
colProps: { span: 12 },
componentProps: {
rows: 4,
slice: [30, 35, 40]
},
},
]
@ -2106,7 +2106,8 @@ export const cargoInfoFormSchema3: FormSchema[] = [
option: optionsStore.getOptionsByCode('GetClientGoodsList'),
allowClear: true,
showSearch: true,
labelField: 'goodName',
labelField: 'pinYinCode',
showName: 'goodName',
valueField: 'id',
filterOption: (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
@ -2116,6 +2117,8 @@ export const cargoInfoFormSchema3: FormSchema[] = [
formModel.goodsName = obj.label
if (obj.hsCode) {
formModel.hsCode = obj.hsCode
} else {
formModel.hsCode = null
}
} else {
formModel.goodsName = ''

@ -15,6 +15,14 @@
<template #status="{ model }">
<a-switch @change="changeStatus" v-model:checked="model.status" /> <span class="s-txt" :class="{ 's-active': model.status }">{{ model.status ? '启用' : '禁用'}}</span>
</template>
<template #files>
<DsFile :maxCount="10" ref="dsFile" :id="rowId" :show="false" height="300">
<a-button type="link" size="mini" style="padding-right: 3px!important;" @click="addFile">
<span class="iconfont icon-fujian1"></span>
点击上传附件
</a-button>
</DsFile>
</template>
</BasicForm>
</a-tab-pane>
<a-tab-pane key="1" tab="账户信息" force-render>
@ -240,6 +248,11 @@
linkId: linkId.value,
})
}
//
const dsFile = ref(null)
function addFile() {
dsFile.value.init()
}
function EditBank(record: Recordable) {
openModal(true, {
record,

@ -422,6 +422,19 @@ export const formSchema: FormSchema[] = [
span: 6,
},
},
{
field: 'files',
slot: 'files',
component: 'Input',
label: 'LOGO、营业执照、NOVCC等、公章/电放章/SW章',
defaultValue: false,
show: ({ values }) => {
return !!values.id
},
colProps: {
span: 24
}
}
]
export const BankColumns: BasicColumn[] = [

@ -82,7 +82,7 @@
<span class="s-txt" :class="{ 's-active': model.isLimitClient }">{{ model.isLimitClient ? '是' : '否'}}</span>
</template>
<template #signatureUrl>
<DsFile v-if="id" :maxCount="1" ref="dsFile" :id="id" :show="false" height="300">
<DsFile :maxCount="1" ref="dsFile" :id="rowId" :show="false" height="300">
<a-button type="link" size="mini" style="padding-right: 3px!important;" @click="addFile">
<span class="iconfont icon-fujian1"></span>
点击上传图片
@ -94,7 +94,7 @@
<a-tab-pane key="1" tab="个人开户信息">
<BankInfo
v-if="activeKey == 1"
:id="id"
:id="rowId"
></BankInfo>
</a-tab-pane>
</a-tabs>
@ -128,6 +128,7 @@
const emit = defineEmits(['success', 'register'])
const isUpdate = ref(true)
const loading = ref(false)
// id
const rowId = ref('')
const { createMessage } = useMessage()
const activeKey = ref('0')
@ -137,9 +138,6 @@
schemas: formSchema,
showActionButtonGroup: false,
})
// id
const id = ref('')
const fileList = ref([])
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
activeKey.value = '0'
resetFields()
@ -150,7 +148,6 @@
rowId.value = data.record.id
const res: API.DataResult = await getUser({ id: unref(rowId) })
if (res.succeeded) {
id.value = res.data.id
setFieldsValue({
...res.data,
})
@ -173,7 +170,6 @@
createMessage.success(res.message)
emit('success')
}
exit && closeModal()
} finally {
setModalProps({ confirmLoading: false, loading: false })
@ -183,14 +179,14 @@
function addFile() {
dsFile.value.init()
}
async function refresh() {
const res: API.DataResult = await getUser({ id: unref(rowId) })
if (res.succeeded) {
await setFieldsValue({
...res.data,
})
}
}
// async function refresh() {
// const res: API.DataResult = await getUser({ id: unref(rowId) })
// if (res.succeeded) {
// await setFieldsValue({
// ...res.data,
// })
// }
// }
</script>
<style lang="less" scoped>

@ -446,6 +446,9 @@ export const formSchema: FormSchema[] = [
label: '上传签名照',
slot: 'signatureUrl',
component: 'Input',
show: ({ values }) => {
return !!values.id
},
colProps: { span: 24 }
},
]

Loading…
Cancel
Save