前言
在准备将谷歌浏览器插件上架应用市场时,必须填写隐私协议声明,并提供一个可直接访问的链接地址,无法上传 txt 文件。
然后我在网上找到一个工具,能快速生成隐私协议,只需要填写产品名称、作者、公司等信息,勾选相关选项,便可自动生成协议,确实非常方便。可惜的是,它竟然要收费 5 元才能一键在线部署,显然我是不打算支付这笔费用的!(狗头)😝
所以打算自己做一个并开源,让大家都能免费使用。
开始制作
直接 vite 起手一个模板项目,然后 tailwind 来写样式
上一篇文章分享过高效使用 cursor 的方法,我直接拿来网上收费软件的截图发给 cursor。 由于做的过程中没有截图记录,这里直接展示成品界面。
首页
填写产品名称后,进入到一个三步表单。收集用户输入的相关信息,这里使用react-hook-form
来管理Form表单相关的数据。
// 表单步骤
const [currentStep, setCurrentStep] = useState<FormStep>(1);
// 生成的内容结果
const [generatedContent, setGeneratedContent] = useState<string>('');
const {
register,
handleSubmit,
watch,
} = useForm<FormData>({
defaultValues: {
productName: productName,
productType: 'App',
collectUserInfo: true,
collectInfo: {
phone: false,
email: false,
preferences: false,
},
collectMethod: {
registration: false,
thirdParty: false,
},
scope: 'selfUse',
protection: {
encryption: false,
keepAfterDelete: false,
},
deletion: {
deleteWhenNotNeeded: false,
allowUserDelete: false,
},
useCookies: false,
attractChildren: false,
},
});
// 监听收集信息开关的状态
const collectUserInfo = watch('collectUserInfo');
const onSubmit = (data: FormData) => {
if (currentStep === 2) {
// 生成隐私政策内容
setGeneratedContent(JSON.stringify(data));
nextStep();
} else {
nextStep();
}
};
const nextStep = () => {
if (currentStep < 3) {
setCurrentStep((prev) => (prev + 1) as FormStep);
}
};
const prevStep = () => {
if (currentStep > 1) {
setCurrentStep((prev) => (prev - 1) as FormStep);
}
};
Dom 部分我这里就主要展示下重要的内容吧,form 表单项就不贴在这里了,然后还需要封装一个在第三步呈现表单数据预览的 Result 组件。需要的可以在末尾查看源码。
<div className="p-6 mx-auto max-w-4xl">
{/* 步骤指示器 */}
<div className="mb-8 ml-[100px] flex items-center justify-between px-6">
{[
{ step: 1, label: '基本配置' },
{ step: 2, label: '附加选项' },
{ step: 3, label: '生成结果' },
].map(({ step, label }) => (
<div key={step} className="flex flex-1 items-center">
<div className="flex items-center">
<div
className={`
flex h-8 w-8 items-center justify-center rounded-full
${
step === currentStep
? 'bg-blue-600 text-white'
: step < currentStep
? 'bg-green-500 text-white'
: 'bg-gray-200 text-gray-600'
}
`}
>
{step}
</div>
<span className="ml-2 text-sm text-gray-600">{label}</span>
</div>
{step < 3 && (
<div
className={`mx-4 h-[1px] flex-1 ${
step < currentStep ? 'bg-green-500' : 'bg-gray-200'
}`}
/>
)}
</div>
))}
</div>
{currentStep === 3 ? (
<Result
onBack={() => setCurrentStep(2)}
formData={JSON.parse(generatedContent)}
/>
) : (
<form
onSubmit={handleSubmit(onSubmit)}
className="p-6 bg-white rounded-lg shadow-sm"
>
{currentStep === 1 && (
<div>第一部分相关的表单项 这里省略不贴了...</div>
)}
{currentStep === 2 && (
<div>>第二部分相关的表单项 这里省略不贴了...</div>
)}
<div className="flex justify-between mt-8">
<button
type="button"
onClick={prevStep}
className={`rounded-lg px-6 py-2 ${
currentStep === 1
? 'cursor-not-allowed bg-gray-100 text-gray-400'
: 'bg-gray-100 text-gray-600 hover:bg-gray-200'
}`}
disabled={currentStep === 1}
>
{currentStep === 1 ? '取消' : '上一步'}
</button>
<button
type="submit"
className="px-6 py-2 text-white bg-blue-600 rounded-lg hover:bg-blue-700"
>
{currentStep === 2 ? '确认生成' : '下一步'}
</button>
</div>
</form>
)}
</div>
最后根据 Form 的数据呈现生成的协议内容。
这里跟 AI 老师学到了如何将预览的 React 组件输出为 html 文件。原来有一个方法叫做outerHTML
developer.mozilla.org/zh-CN/docs/…
我这里生成文件夹的原因是为了后续上传 netify 需要是文件夹内放一个 index.html的形式。
const downloadHtmlFile = () => {
if (templateRef.current) {
const html = templateRef.current.outerHTML;
const zip = new JSZip();
zip.folder(formData.productName)?.file('index.html', html);
zip.generateAsync({ type: 'blob' }).then(function (blob) {
const element = document.createElement('a');
element.href = URL.createObjectURL(blob);
element.download = `${formData.productName}.zip`;
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
});
}
};
然后用户点击下载 HTML后根据下方的教程指引部署到 netify,很简单,登录账号后把下载好的文件夹拖拽上传即可。
然后就可以愉快的将获取到的这个在线地址贴在需要使用的地方啦~
使用 CI 部署到 github Page
在项目根目录创建 .github/workflows/deploy-pages.yml
文件
name: Deploy to GitHub Pages
on:
push:
branches:
- main
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 9
- name: Install dependencies
run: pnpm install
- name: Build
run: pnpm build
- name: Setup Pages
uses: actions/configure-pages@v4
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: "dist"
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
在 push 到仓库 setting 中开启 github action 这样我们代码 push 到 main 分支就可以自动更新到 github page 了
源码
在线地址: llmoskk.github.io/privacy-pol…
仓库源码: github.com/LLmoskk/pri…
结语
全程使用 cursor 辅助开发 总耗时 4 小时左右,主要费时在根据条件控制隐私协议的生成的内容上 😂,cursor 会删掉一些话,可能是文本太长了,我自己花时间人工校验的。希望对大家有帮助~